NAME¶
huddle - Create and manipulate huddle object
SYNOPSIS¶
package require
Tcl 8.4
package require
huddle ?0.1.5?
huddle create key value ?
key value ...?
huddle list ?
value value ...?
huddle get object key ?
key ...?
huddle gets object key ?
key ...?
huddle set objectVar key ?
key ...?
value
huddle remove object key ?
key ...?
huddle combine object1 object2 ?
object3 ...?
huddle equal object1 object2
huddle append objectVar key value ?
key value
...?
huddle append objectVar value ?
value ...?
huddle keys object
huddle llength object
huddle type object ?
key key...?
huddle strip object
huddle jsondump object ?
offset? ?
newline?
?
begin_offset?
huddle compile spec data
huddle isHuddle object
huddle checkHuddle object
huddle to_node object ?
tag?
huddle wrap tag src
huddle call tag command args
huddle addType callback
callback command ?
args?
setting
get_sub src key
strip src
set src key value
remove src key value
DESCRIPTION¶
Huddle provides a generic Tcl-based serialization/intermediary format.
Currently, each node is wrapped in a tag with simple type information.
When converting huddle-notation to other serialization formats like JSON or YAML
this type information is used to select the proper notation. And when going
from JSON/YAML/... to huddle their notation can be used to select the proper
huddle type.
In that manner huddle can serve as a common intermediary format.
huddle-format: >
{HUDDLE {huddle-node}}
huddle-node: >
{tag content}
each content of tag means:
s: (content is a) string
L: list, each sub node is a huddle-node
D: dict, each sub node is a huddle-node
confirmed:
- JSON
- YAML(generally, but cannot discribe YAML-tags)
limitation:
- cannot discribe aliases from a node to other node.
The
huddle package returns data as a Tcl
dict. Either the
dict package or Tcl 8.5 is required for use.
COMMANDS¶
- huddle create key value ?key value ...?
- Create a huddle object as a dict. It can contain other huddle
objects.
- huddle list ?value value ...?
- Create a huddle object as a list. It can contain other huddle
objects.
- huddle get object key ?key ...?
- Almost the same as dict get. Get a sub-object from the huddle
object. key can be used to huddle-list's index.
- huddle gets object key ?key ...?
- Get a sub-object from the huddle object, stripped.
- huddle set objectVar key ?key ...?
value
- Almost the same as dict set. Set a sub-object from the huddle
object. key can be used to huddle-list's index.
- huddle remove object key ?key ...?
- Almost the same as dict remove. Remove a sub-object from the huddle
object. key can be used to huddle-list's index.
- huddle combine object1 object2 ?object3
...?
- Merging huddle objects given.
% set aa [huddle create a b c d]
HUDDLE {D {a {s b} c {s d}}}
% set bb [huddle create a k l m]
HUDDLE {D {a {s k} l {s m}}}
% huddle combine $aa $bb
HUDDLE {D {a {s k} c {s d} l {s m}}}
- huddle equal object1 object2
- Comparing two huddle objects recursively. When to equal, returns 1,
otherwise 0.
% set aa [huddle create a b c d]
HUDDLE {D {a {s b} c {s d}}}
% set bb [huddle create c d a b]
HUDDLE {D {c {s d} a {s b}}}
% huddle equal $aa $bb
1
- huddle append objectVar key value ?key
value ...?
- huddle append objectVar value ?value ...?
- Appending child elements. When for dicts, giving key/value. When for
lists, giving values.
% set aa [huddle create a b c d]
HUDDLE {D {a {s b} c {s d}}}
% huddle append aa a k l m
HUDDLE {D {a {s k} c {s d} l {s m}}}
% set bb [huddle list i j k l]
HUDDLE {L {{s i} {s j} {s k} {s l}}}
% huddle append bb g h i
HUDDLE {L {{s i} {s j} {s k} {s l} {s g} {s h} {s i}}}
- huddle keys object
- The same as dict keys.
- huddle llength object
- The same as llength.
- huddle type object ?key key...?
- Return the element type of specified by keys. if ?key? is not given,
returns the type of root node.
- string
- the node is a tcl's string.
- dict
- the node is a dict.
- list
- the node is a list.
% huddle type {HUDDLE {s str}}
string
% huddle type {HUDDLE {L {{s a} {s b} {s c}}}}
list
% huddle type {HUDDLE {D {aa {s b} cc {s d}}}} cc
string
- huddle strip object
- Stripped all tags. Converted to normal Tcl's list/dict.
- huddle jsondump object ?offset? ?newline?
?begin_offset?
- dump a json-stream from the huddle-object.
- offset ""
- begin offset as spaces " ".
# normal output has some indents. some strings are escaped.
% huddle jsondump {HUDDLE {L {{L {{s i} {s baa} {s \\k} {L {{s 1.0} {s true} {s /g} {s h}}} {L {{s g}}}}} {s t}}}}
[
[
"i",
"baa",
"\\k",
[
1.0,
true,
"\/g",
"h"
],
["g"]
],
"t"
]
# stripped output
% huddle jsondump {HUDDLE {D {dd {D {bb {D {a {s baa} c {s {d
a}}}} cc {D {g {s h}}}}} ee {D {i {s j} k {s 1} j {s { m\a}}}}}}} "" ""
{"dd": {"bb": {"a": "baa","c": "d\na"},"cc": {"g": "h"}},"ee": {"i": "j","k": 1,"j": " m\\a"}}
- huddle compile spec data
- construct a huddle object from plain old tcl values. spec is
defined as follows:
- string
- data is simply a string
- list
- data is a tcl list of strings
- dict
- data is a tcl dict of strings
- list list
- data is a tcl list of lists
- list dict
- data is a tcl list of dicts
- dict xx list
- data is a tcl dict where the value of key xx is a tcl list
- dict * list
- data is a tcl dict of lists data is plain old tcl values
% huddle compile {dict * list} {a {1 2 3} b {4 5}}
HUDDLE {D {a {L {{s 1} {s 2} {s 3}}} b {L {{s 4} {s 5}}}}}
% huddle compile {dict * {list {dict d list}}} {a {{c 1} {d {2 2 2} e 3}} b {{f 4 g 5}}}
HUDDLE {D {a {L {{D {c {s 1}}} {D {d {L {{s 2} {s 2} {s 2}}} e {s 3}}}}} b {L {{D {f {s 4} g {s 5}}}}}}}
- huddle isHuddle object
- if object is a huddle, returns 1. the other, returns 0.
- huddle checkHuddle object
- if object is not a huddle, rises an error.
- huddle to_node object ?tag?
- for type-callbacks.
if object is a huddle, returns root-node. the other, returns [list
s $object].
% huddle to_node str
s str
% huddle to_node str !!str
!!str str
% huddle to_node {HUDDLE {s str}}
s str
% huddle to_node {HUDDLE {l {a b c}}}
l {a b c}
- huddle wrap tag src
- for type-callbacks.
Create a huddle object from src with specified tag.
% huddle wrap "" str
HUDDLE str
% huddle wrap s str
HUDDLE {s str}
- huddle call tag command args
- for type-callbacks.
devolving command to default tag-callback
- huddle addType callback
- add a user-specified-type/tag to the huddle library. To see
"Additional Type".
- callback
- callback function name for additional type.
TYPE CALLBACK¶
The definition of callback for user-type.
- callback command ?args?
- command
- huddle subcomand which is needed to reply by the callback.
- args
- arguments of subcommand. The number of list of arguments is different for
each subcommand.
The callback procedure shuould reply the following subcommands.
- setting
- only returns a fixed dict of the type infomation for setting the
user-tag.
- type typename
- typename of the type
- method {method1 method2 method3 ...}
- method list as huddle subcommand. Then, you can call [huddle method1
...]
- tag {tag1 child/parent tag2 child/parent ...}
- tag list for huddle-node as a dict. if the type has child-nodes, use
"parent", otherwise use "child".
- get_sub src key
- returns a sub node specified by key.
- src
- a node content in huddle object.
- strip src
- returns stripped node contents. if the type has child nodes, every node
must be stripped.
- set src key value
- sets a sub-node from the tagged-content, and returns self.
- remove src key value
- removes a sub-node from the tagged-content, and returns self.
strip must be defined at all types.
get_sub must be defined at
container types.
set/remove shuould be defined, if you call them.
# callback sample for my-dict
proc my_dict_setting {command args} {
switch -- $command {
setting { ; # type definition
return {
type dict
method {create keys}
tag {d child D parent}
constructor create
str s
}
# type: the type-name
# method: add methods to huddle's subcommand.
# "get_sub/strip/set/remove/equal/append" called by huddle module.
# "strip" must be defined at all types.
# "get_sub" must be defined at container types.
# "set/remove/equal/append" shuould be defined, if you call them.
# tag: tag definition("child/parent" word is maybe obsoleted)
}
get_sub { ; # get a sub-node specified by "key" from the tagged-content
foreach {src key} $args break
return [dict get $src $key]
}
strip { ; # strip from the tagged-content
foreach {src nop} $args break
foreach {key val} $src {
lappend result $key [huddle strip $val]
}
return $result
}
set { ; # set a sub-node from the tagged-content
foreach {src key value} $args break
dict set src $key $value
return $src
}
remove { ; # remove a sub-node from the tagged-content
foreach {src key value} $args break
return [dict remove $src $key]
}
equal { ; # check equal for each node
foreach {src1 src2} $args break
if {[llength $src1] != [llength $src2]} {return 0}
foreach {key1 val1} $src1 {
if {![dict exists $src2 $key1]} {return 0}
if {![huddle _equal_subs $val1 [dict get $src2 $key1]]} {return 0}
}
return 1
}
append { ; # append nodes
foreach {str src list} $args break
if {[llength $list] % 2} {error {wrong # args: should be "huddle append objvar ?key value ...?"}}
set resultL $src
foreach {key value} $list {
if {$str ne ""} {
lappend resultL $key [huddle to_node $value $str]
} else {
lappend resultL $key $value
}
}
return [eval dict create $resultL]
}
create { ; # $args: all arguments after "huddle create"
if {[llength $args] % 2} {error {wrong # args: should be "huddle create ?key value ...?"}}
set resultL {}
foreach {key value} $args {
lappend resultL $key [huddle to_node $value]
}
return [huddle wrap D $resultL]
}
keys {
foreach {src nop} $args break
return [dict keys [lindex [lindex $src 1] 1]]
}
default {
error "$command is not callback for dict"
}
}
}
# inheritance sample from default dict-callback
proc ::yaml::_huddle_mapping {command args} {
switch -- $command {
setting { ; # type definition
return {
type dict
method {mapping}
tag {!!map parent}
constructor mapping
str !!str
}
}
mapping { ; # $args: all arguments after "huddle mapping"
if {[llength $args] % 2} {error {wrong # args: should be "huddle mapping ?key value ...?"}}
set resultL {}
foreach {key value} $args {
lappend resultL $key [huddle to_node $value !!str]
}
return [huddle wrap !!map $resultL]
}
default { ; # devolving to default dict-callback
return [huddle call D $command $args]
}
}
}
HOW TO ADD TYPE¶
You can add huddle-node types e.g. ::struct::tree. To do so, first, define a
callback-procedure for additional tagged-type. The proc get argments as
command and ?
args?. It has some switch-sections.
And, addType subcommand will called.
huddle addType my_dict_setting
WORKING SAMPLE¶
# create as a dict
% set bb [huddle create a b c d]
HUDDLE {D {a {s b} c {s d}}}
# create as a list
% set cc [huddle list e f g h]
HUDDLE {L {{s e} {s f} {s g} {s h}}}
% set bbcc [huddle create bb $bb cc $cc]
HUDDLE {D {bb {D {a {s b} c {s d}}} cc {L {{s e} {s f} {s g} {s h}}}}}
% set folding [huddle list $bbcc p [huddle list q r] s]
HUDDLE {L {{D {bb {D {a {s b} c {s d}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q} {s r}}} {s s}}}
# normal Tcl's notation
% huddle strip $folding
{bb {a b c d} cc {e f g h}} p {q r} s
# get a sub node
% huddle get $folding 0 bb
HUDDLE {D {a {s b} c {s d}}}
% huddle gets $folding 0 bb
a b c d
# overwrite a node
% huddle set folding 0 bb c kkk
HUDDLE {L {{D {bb {D {a {s b} c {s kkk}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q} {s r}}} {s s}}}
# remove a node
% huddle remove $folding 2 1
HUDDLE {L {{D {bb {D {a {s b} c {s kkk}}} cc {L {{s e} {s f} {s g} {s h}}}}} {s p} {L {{s q}}} {s s}}}
% huddle strip $folding
{bb {a b c kkk} cc {e f g h}} p {q r} s
# dump as a JSON stream
% huddle jsondump $folding
[
{
"bb": {
"a": "b",
"c": "kkk"
},
"cc": [
"e",
"f",
"g",
"h"
]
},
"p",
[
"q",
"r"
],
"s"
]
LIMITATIONS¶
now printing.
BUGS, IDEAS, FEEDBACK¶
This document, and the package it describes, will undoubtedly contain bugs and
other problems. Please report such in the category
huddle of the
Tcllib Trackers [
http://core.tcl.tk/tcllib/reportlist]. Please also
report any ideas for enhancements you may have for either package and/or
documentation.
SEE ALSO¶
yaml
KEYWORDS¶
data exchange, exchange format, huddle, json, parsing, text processing, yaml
COPYRIGHT¶
Copyright (c) 2008 KATO Kanryu <kanryu6@users.sourceforge.net>