---
name: "huddle"
section: "3tcl"
platform: "linux"
package: "tcllib"
version: "2.0+dfsg-4"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/huddle"
---

# huddle(3tcl)

Create and manipulate huddle object

```

```

## NAME

huddle - Create and manipulate huddle object

## SYNOPSIS

package require **Tcl 8.5 9**

package require **huddle ?0.5?**

**huddle create** *key* *value* ?*key value ...*?

**huddle list** ?*value value ...*?

**huddle number** *number*

**huddle string** *string*

**huddle boolean** *expression to evaluate as true or false*

**huddle true**

**huddle false**

**huddle null**

**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 number** *number*

  Create a huddle object as a number.

- **huddle string** *string*

  Create a huddle object as a string.

- **huddle boolean** *expression to evaluate as true or false*

  Create a huddle object as a boolean evaluating an expression as true or false-

- **huddle true**

  Create a huddle object as a boolean true.

- **huddle false**

  Create a huddle object as a boolean false.

- **huddle null**

  Create a huddle object as a null.

- **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.

  - **number**

    the node is a number.

  - **boolean**

    the node is a boolean.

  - **null**

    the node is a null.

  ```
  % 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.

When proposing code changes, please provide *unified diffs*, i.e the output of **diff -u**.

Note further that *attachments* are strongly preferred over inlined patches. Attachments can be made by going to the **Edit** form of the ticket immediately after its creation, and then using the left-most button in the secondary navigation bar.

## SEE ALSO

yaml

## KEYWORDS

data exchange, exchange format, huddle, json, parsing, text processing, yaml

## COPYRIGHT

```
Copyright (c) 2008-2011 KATO Kanryu <kanryu6@users.sourceforge.net>
Copyright (c) 2015 Miguel Martínez López <aplicacionamedida@gmail.com>
```
