YAML and LiveCode
Posted: Thu Aug 28, 2014 2:52 am
				
				I found a reference to one or more JSON libraries for LC. Are there any libraries for YAML?
			Questions and answers about the LiveCode platform.
https://www.forums.livecode.com/
Code: Select all
/**
Array-to-Yaml and Yaml-to-Array library
Mark Wieder 2016
wtf licenced : have fun
Public functions here:
arrayToYaml
yamlToArray
yamlFileToArray
*/
-- allow 4 spaces per indentation in output yaml files
-- adjust as desired
constant kIndent = 4
/*
arrayToYaml
Convert a LiveCode array to yaml format
@pArray : the array to convert
@pIndentLevel : initially empty, recursion sets this
*/
function arrayToYaml pArray, pIndentLevel
   local tYaml
   local tIndentLevel
   
   put pIndentLevel into tIndentLevel
   if tIndentLevel is empty then
      put kIndent into tIndentLevel
      put "ArrayName :" & cr into tYaml
   end if
   if pArray is an array then
      repeat for each key tKey in pArray
         if pArray[tKey] is an array then
            put indent(tIndentLevel) & tKey && ":" && pArray[tKey] & cr after tYaml
            add kIndent to tIndentLevel
            -- recurse to work through multidimensional arrays
            put arrayToYaml(pArray[tKey], tIndentLevel) after tYaml
            subtract kIndent from tIndentLevel
         else
            put indent(tIndentLevel) & tKey && ":" && pArray[tKey] & cr after tYaml
         end if
      end repeat
   else
      throw "not an array"
   end if
   return tYaml
end arrayToYaml
/*
indent
Used internally by arrayToYaml
*/
private function indent pIndentLevel
   local tIndentLevel
   
   -- return the proper number of spaces for indentation
   repeat pIndentLevel times
      put space after tIndentLevel
   end repeat
   return tIndentLevel
end indent
/*
indentationLevel
Return the indentation level of the supplied line
NOTE: changes the input line in situ to remove the indentation
Used internally by yamlToArray
*/
private function indentationLevel @pLine
   local tIndentationLevel
   local tKey, tValue
   
   put 0 into tIndentationLevel
   repeat while char 1 of pLine is space
      add 1 to tIndentationLevel
      delete char 1 of pLine
   end repeat
   return tIndentationLevel
end indentationLevel
/*
yamlToArray
Convert yaml format text to a LiveCode array
*/
function yamlToArray pYaml
   local tArray
   local tIndentation, tPrevIndent
   local tWorkingLine
   local tYamlHeading
   local tKey, tValue
   
   repeat for each line tLine in pYaml
      put tLine into tWorkingLine
      set the itemdelimiter to ":"
      put item 1 of tWorkingLine into tKey
      repeat while char -1 of tKey is in ": "
         delete char -1 of tKey
      end repeat
      put word 1 to -1 of item 2 of tWorkingLine into tValue
      put indentationLevel(tKey) into tIndentation
      if tPrevIndent is empty then
         -- first time through
         put tIndentation into tPrevIndent
         put tKey into tYamlHeading
         put tValue into tArray[tYamlHeading]
      else
         switch
            case tIndentation < tPrevIndent
               -- remove the last array index
               RemoveLastIndexFrom tYamlHeading
               RemoveLastIndexFrom tYamlHeading
               put tIndentation into tPrevIndent
               if tYamlHeading is empty then
                  do "put tValue into tArray[" & tKey & "]"
               else
                  do "put tValue into tArray" & yamlPathToArrayPath(tYamlHeading) & "[" & tKey & "]"
               end if
               break
            case tIndentation is tPrevIndent
               RemoveLastIndexFrom tYamlHeading
               if tYamlHeading is empty then
                  do "put tValue into tArray" & "[" & tKey & "]"
               else
                  do "put tValue into tArray" & yamlPathToArrayPath(tYamlHeading) & "[" & tKey & "]"
               end if
               put comma & tKey after tYamlHeading
               break
            case tIndentation > tPrevIndent
               -- add an array index
               if tYamlHeading is empty then
                  do "put tValue into tArray[" & tKey & "]"
               else
                  do "put tValue into tArray" & yamlPathToArrayPath(tYamlHeading) & "[" & tKey & "]"
               end if
               put comma & tKey after tYamlHeading
               put tIndentation into tPrevIndent
               break
         end switch
      end if
   end repeat
   return tArray
end yamlToArray
private command RemoveLastIndexFrom @pIndexString
   set the itemdelimiter to comma
   delete item -1 of pIndexString
end RemoveLastIndexFrom
private function yamlPathToArrayPath pYamlPath
   local tArrayPath
   
   set the itemdelimiter to comma
   repeat for each item tPath in pYamlPath
      put "[" & tPath & "]" after tArrayPath
   end repeat
   return tArrayPath
end yamlPathToArrayPath
/*
yamlFileToArray
Point to a yaml file, return a LiveCode array
*/
function yamlFileToArray pFilePath
   local tYaml
   
   put url ("file:" & pFilePath) into tYaml
   return yamlToArray(tYaml)
end yamlFileToArray
/*
*/
command testArrayToYaml
   local tArray
   
   put "hello" into tArray["hi"]
   put "bucko" into tArray["greeting"]["name"]
   put 1234 into tArray["greeting"]["mynumber"]
   put "goodbye" into tArray["bye"]
   put "510-555-1212" into tArray["greeting"]["phonenumber"]["landline"]
   put "510-555-1212" into tArray["greeting"]["phonenumber"]["cell"]
   put arrayToYaml(tArray)
end testArrayToYaml
command testYamlToArray
   local tYaml
   
   put "greeting :" & cr into tYaml
   put "    myNumber : 1234" & cr after tYaml
   put "    phonenumber :" & cr after tYaml
   put "        landline : 510-555-4567" & cr after tYaml
   put "            extension : 42" & cr after tYaml
   put "        cell : 510-555-1234" & cr after tYaml
   put "    name : bucko" & cr after tYaml
   put "hi : hello" & cr after tYaml
   put "bye : goodbye" & cr after tYaml
   put arrayToYaml(yamlToArray(tYaml)) & cr after msg
end testYamlToArrayCode: Select all
name: Mark McGwire
hr:   65
avg:  0.278
Code: Select all
- Mark McGwire
- Sammy Sosa
- Ken Griffey
Code: Select all
hr:  65    # Home runs
avg: 0.278 # Batting average
rbi: 147   # Runs Batted In
Code: Select all
# Lists inside array
american:
  - Boston Red Sox
  - Detroit Tigers
  - New York Yankees
national:
  - New York Mets
  - Chicago Cubs
  - Atlanta Braves
Code: Select all
# Arrays inside list
-
  name: Mark McGwire
  hr:   65
  avg:  0.278
-
  name: Sammy Sosa
  hr:   63
  avg:  0.288
Code: Select all
- [name        , hr, avg  ]
- [Mark McGwire, 65, 0.278]
- [Sammy Sosa  , 63, 0.288]
Code: Select all
name: Mark McGwire
accomplishment: >
  Mark set a major league
  home run record in 1998.
stats: |
  65 Home Runs
  0.278 Batting Average
Code: Select all
---
hr:
  - Mark McGwire
  # labels this node as 'SS'
  - &SS Sammy Sosa
rbi:
  - *SS # previous node reference
  - Ken Griffey
Code: Select all
---
time: 20:03:20
player: Sammy Sosa
action: strike (miss)
...
---
time: 20:03:47
player: Sammy Sosa
action: grand slam
...
Code: Select all
--- !<tag:clarkevans.com,2002:invoice>
invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
ship-to: *id001
product:
    - sku         : BL394D
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.
Not at all. It's the key/value hierarchy that's important, not the placement.I use these functions to deal with my ruby yaml files.it seems to expect that every line of the inputted YAML will always be in 'array' (key:value) format - like this:
Code: Select all
action:
  accounts : 'Accounts'
  launch_scan : 'Launch Scan'
  view_scan_requests : 'View Scan Requests'
  view_scan_results : 'View Scan Results'
findings:
  day : 'Today'
  week : 'Week'
  month : 'Month'
policy_rules:
  all : 'all'
  email : 'email'
  malware : 'malware'
  network : 'network'
  web : 'web'Not exactly. It's a similar format though, especially with YAML 1.2.YAML is actually a superset of JSON
It would be truly useful to have a fully-compliant YAML parser in LiveCode. There are many web frameworks that use .yaml files either for configuration or data storage, or both, and LiveCode would have been a great tool to be able to produce GUIs for these.(...)YAML can therefore be viewed as a natural superset of JSON, offering improved human readability and a more complete information model. This is also the case in practice; every JSON file is also a valid YAML file. This makes it easy to migrate from JSON to YAML if/when the additional features are required.
Code: Select all
local tYQCommand, tJSON, tArray
put "path/to/yq r -j" && "path/to/sample.yml" into tYQCommand
put shell(tYQCommand) into tJSON
put JSONToArray(tJSON) into tArray