Skip to content

Instantly share code, notes, and snippets.

@petrowsky
Last active July 23, 2024 21:40
Show Gist options
  • Save petrowsky/bdca27e4b611af6ffbcddc50fceed614 to your computer and use it in GitHub Desktop.
Save petrowsky/bdca27e4b611af6ffbcddc50fceed614 to your computer and use it in GitHub Desktop.
DevTools_SetVarSteps2JSON
/*
* DevTools_SetVarSteps2JSON ( option ; dataType )
*
* Quite possibly one of the most valuable functions none of
* your end users will ever use! This one is for you, the developer.
*
* HINT: Copy any number of Set Variable[] script steps to your clipboard
* and use this function within the Data Viewer. Set parameters initially to blank.
*
* @requires: BaseElements plug-in
*
* @parameter: option = A numerical value no greater than the number of ~templates.
*
* @parameter: dataType = A valid JSON* type value.
*
* @returns: [function] Returns a JSONSetElement() function.
*
* @version: 2024-07-23-01
*
* @history: 2024-06 - Matt Petrowsky - Created
* https://www.filemakermagazine.com
*
* @source: https://gist.github.com/petrowsky/bdca27e4b611af6ffbcddc50fceed614
*/
Let ( [
// User input options.
~choice = option;
~dataType = dataType;
// Valid JSONSetElement() types.
~validTypes = List (
"JSONString" ;
"JSONNumber" ;
"JSONObject" ;
"JSONArray" ;
"JSONBoolean" ;
"JSONNull" ;
"JSONRaw" ;
);
// BaseElements plug-in Set Variable[] step extraction.
~stepsFormat = Choose ( Abs ( Get ( SystemPlatform ) ) - 1 ; "dyn.ah62d4rv4gk8zuxnxnq" ; "Mac-XMSS" );
~clipboardFormat = GetValue ( BE_ClipboardFormats ; 1 );
~validFormat = ~clipboardFormat = ~stepsFormat;
~snippet = If ( ~validFormat ; BE_ClipboardGetText ( ~clipboardFormat ) );
~variableNames = If ( ~validFormat ; BE_XPathAll ( ~snippet ; "//Step[@name='Set Variable']/Name/text()" ) );
// Developer controlled list of possible templates. Add any other desired variations.
~templates = List (
"[ $var ; \"\" ; JSONString ]";
"[ \"\" ; $var ; JSONString ]";
"[ \"var\" ; \"\" ; JSONString ]";
"[ \"\" ; \"var\" ; JSONString ]";
"[ $var ; \"var\" ; JSONString ]";
"[ \"var\" ; $var ; JSONString ]";
"[ $var ; \"$var\" ; JSONString ]";
"[ \"$var\" ; $var ; JSONString ]";
"[ \"$var\" ; \"\" ; JSONString ]";
"[ \"\" ; \"$var\" ; JSONString ]";
"[ \"var\" ; [calculation] ; JSONString ]";
"[ \"$var\" ; [calculation] ; JSONString ]";
"var";
"$var";
);
// Generates a human readable list of options from possible ~templates.
~options = While ( [
~i = 0;
~result = ""
];
~i < ValueCount ( ~templates ) ;
[
~i = ~i + 1;
~number = Right ( "0" & ~i ; 2 );
~value = GetValue ( ~templates ; ~i );
~display = ~number & ") " & ~value;
~isEven = Mod ( ~i ; 2 );
~result = List ( ~result ; If ( ~isEven ; ¶ ) & ~display )
];
~result
);
// Use a template and create the desired result.
~template = GetValue ( ~templates ; ~choice );
~templateParts = Substitute ( ~template ; ";" ; ¶ );
~keyHasDollarSign = Position ( GetValue ( ~templateParts ; 1 ) ; "$" ; 1 ; 1 );
~valueHasDollarSign = Position ( GetValue ( ~templateParts ; 2 ) ; "$" ; 1 ; 1 );
// The magic happens here!
~substitutions = If ( ~validFormat ; While ( [
~i = 0;
~variables = ~variableNames;
~processedVars = "";
~result = ""
];
~i < ValueCount ( ~variables ) ;
[
~i = ~i + 1;
~var = GetValue ( ~variables ; ~i );
~varWithoutDollar = Substitute ( ~var ;
[ "$$" ; "" ];
[ "$" ; "" ]
);
~line = Substitute ( ~template ;
[ "var" ; "§§" ]; // Critical: Modify templates otherwise 'var' may be double replaced!
[ "$§§" ; ~var ];
[ "§§" ; ~varWithoutDollar ];
[ "[calculation]" ; "[+-*/]" ];
[ "[+-*/]" ; BE_XPath ( ~snippet ; "//Step[Name='" & ~var & "']/Value/Calculation/text()" ) ];
[ "JSONString" ; Choose ( ~dataType ; "JSONRaw" ; "JSONString" ; "JSONNumber" ; "JSONObject" ; "JSONArray" ; "JSONBoolean" ; "JSONNull" ) ]
);
~valueExists = not IsEmpty ( FilterValues ( ~var ; ~processedVars ) );
~result = List ( ~result ; If ( not ~valueExists ; ~line ) );
~processedVars = List ( ~processedVars ; ~var )
];
~result
) );
~finalResult = If ( not Position ( ~substitutions ; "[" ; 1 ; 1 ); ~substitutions ;
"JSONSetElement ( \"{}\" ;¶"
& Char ( 9 ) & Substitute ( ~substitutions ; ¶ ; ";¶" & Char ( 9 ) )
&"¶)"
);
// ---------- and the reverse direction ----------
~textFormat = "public.utf8-plain-text";
~clipboardHasText = ~clipboardFormat = ~textFormat;
~clipboardText = If ( ~clipboardHasText ; BE_ClipboardGetText ( ~clipboardFormat ) );
~clipboardTextIsArray = JSONGetElementType ( ~clipboardText ; "" ) = JSONArray;
~clipboardTextIsObject = JSONGetElementType ( ~clipboardText ; "" ) = JSONObject;
~clipboardTextIsJSON = ~clipboardTextIsArray or ~clipboardTextIsObject;
~jsonKeys = Case (
~clipboardTextIsArray;
JSONListValues ( ~clipboardText ; "" );
~clipboardTextIsObject;
JSONListKeys ( ~clipboardText ; "" );
""
);
~snippet = List (
"<fmxmlsnippet type=\"FMObjectList\">";
" {{Step}}";
"</fmxmlsnippet>";
);
~xml = List (
" <Step enable=\"True\" id=\"0\" name=\"Set Variable\">";
" <Value>";
" <Calculation><![CDATA[\"\"]]></Calculation>";
" </Value>";
" <Repetition>";
" <Calculation><![CDATA[1]]></Calculation>";
" </Repetition>";
" <Name>{{var}}</Name>";
" </Step>";
);
~steps = If ( not IsEmpty ( ~jsonKeys ) ; While ( [
~i = 0;
~result = ""
];
~i < ValueCount ( ~jsonKeys ) ;
[
~i = ~i + 1;
~var = GetValue ( ~jsonKeys ; ~i );
~step = Substitute ( ~xml;
[ "{{var}}" ; "$" & ~var ]
);
~result = List ( ~result ; ~step )
];
~result
)
);
~setVarSnippet = Substitute ( ~snippet ;
[ " {{Step}}" ; ~steps ]
)
];
Case (
Evaluate ( "BE_Version" ) = "?";
"Please install the BaseElements plug-in from https://docs.baseelementsplugin.com";
~choice = -2; // Hidden option to return the xml snippet.
~setVarSnippet;
~choice = -1 and not IsEmpty ( ~jsonKeys );
If ( BE_ClipboardSetText ( ~setVarSnippet ; ~stepsFormat );
"The clipboard has been set to Script Steps from your JSON. Paste them into your desired script."
);
~clipboardTextIsJSON;
"JSON on the clipboard. Set the option to -1 to convert to Set Variable Steps.";
not ~validFormat;
"Please copy any number of script steps which include the Set Variable script step to your clipboard.";
If ( not IsEmpty ( GetAsNumber ( ~dataType ) ) ;
GetAsNumber ( ~dataType ) < 0 or GetAsNumber ( ~dataType ) > 6;
IsEmpty ( FilterValues ( ~dataType ; ~validTypes ) )
);
"Please supply a valid data type of one of the following: " & Substitute ( ~validTypes ; ¶ ; ", " );
not IsEmpty ( ~choice ) and GetAsNumber ( ~choice ) < 0 or GetAsNumber ( ~choice ) > ValueCount ( ~templates );
"Not a valid option: Temporarily set to blank or 0 to see available options.";
IsEmpty ( ~choice ) or GetAsNumber ( ~choice ) = 0;
"Please input your desired option.¶" & ~options;
~finalResult
)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment