summaryrefslogtreecommitdiff
path: root/doc/en/weechat_relay_protocol.en.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/en/weechat_relay_protocol.en.adoc')
-rw-r--r--doc/en/weechat_relay_protocol.en.adoc1780
1 files changed, 1780 insertions, 0 deletions
diff --git a/doc/en/weechat_relay_protocol.en.adoc b/doc/en/weechat_relay_protocol.en.adoc
new file mode 100644
index 000000000..7db6bbf80
--- /dev/null
+++ b/doc/en/weechat_relay_protocol.en.adoc
@@ -0,0 +1,1780 @@
+= WeeChat Relay protocol
+:author: Sébastien Helleu
+:email: flashcode@flashtux.org
+:lang: en
+:toc: left
+:toclevels: 3
+:sectnums:
+:docinfo1:
+
+
+[[introduction]]
+== Introduction
+
+This document is the specification of WeeChat Relay protocol: the protocol used
+to relay WeeChat data to clients, which are mostly remote interfaces.
+
+[[terminology]]
+=== Terminology
+
+The following terms are used in this document:
+
+* _relay_: this is the WeeChat with relay plugin, which acts as "server" and
+ allows _clients_ to connect
+* _client_: this is another software, connected to _relay_ via a network
+ connection; in most cases, this _client_ is a remote interface.
+
+[[network_diagram]]
+=== Network diagram
+
+The _clients_ are connected to _relay_ like shown in this diagram:
+
+....
+ ┌──────────┐ Workstation
+ ┌────────┐ ┌───┤ client 1 │ (Linux, Windows,
+ │ irc │◄──┐ ╔═══════════╤═══════╗ │ └──────────┘ BSD, Mac OS X ...)
+ └────────┘ └──╢ │ ║◄───┘ ┌──────────┐
+ ...... ║ WeeChat │ Relay ║◄───────┤ client 2 │ Mobile device
+ ┌────────┐ ┌──╢ │ ║◄───┐ └──────────┘ (Android, iPhone ...)
+ │ jabber │◄──┘ ╚═══════════╧═══════╝ │ ......
+ └────────┘ │ ┌──────────┐
+ ...... └───┤ client N │ Other devices
+ └──────────┘
+
+
+└────────────┘ └───────────────────┘╘══════╛└────────────────────────────────┘
+network servers ncurses interface relay remote interfaces
+ protocol
+....
+
+[NOTE]
+All clients here are clients using _weechat_ protocol in _relay_ plugin. The
+_relay_ plugin also allows IRC clients, then _relay_ plugin acts as an
+_IRC proxy_ (not described in this document).
+
+[[protocol_generalities]]
+== Protocol generalities
+
+* Connections from _client_ to _relay_ are made using TCP sockets on IP/port
+ used by _relay_ plugin to listen to new connections.
+* Number of _clients_ is limited by the option _relay.network.max_clients_.
+* Each _client_ is independent from other clients.
+* Messages from _client_ to _relay_ are called _commands_, they are sent as text
+ (a string).
+* Messages from _relay_ to _client_ are called _messages_, they are sent as
+ binary data.
+
+[[commands]]
+== Commands (client → relay)
+
+Commands have format: "(id) command arguments\n".
+
+Fields are:
+
+* _id_: optional message identifier that will be sent in answer from _relay_;
+ it must be enclosed in parentheses, and must not start with an underscore
+ ("_") (ids starting with underscore are reserved for WeeChat _event_ messages)
+* _command_: a command (see table below)
+* _arguments_: optional arguments for command (many arguments are separated by
+ spaces).
+
+List of available commands (detail in next chapters):
+
+[width="80%",cols="^3m,14",options="header"]
+|===
+| Command | Description
+| init | Initialize connection with _relay_
+| hdata | Request a _hdata_
+| info | Request an _info_
+| infolist | Request an _infolist_
+| nicklist | Request a _nicklist_
+| input | Send data to a buffer (text or command)
+| sync | Synchronize buffer(s) (get updates for buffer(s))
+| desync | Desynchronize buffer(s) (stop updates for buffer(s))
+| quit | Disconnect from _relay_
+|===
+
+[[command_init]]
+=== init
+
+Initialize connection with _relay_. This must be first command sent to _relay_.
+If not sent, _relay_ will close connection on first command received, without
+warning.
+
+Syntax:
+
+----
+init [<option>=<value>,[<option>=<value>,...]]
+----
+
+Arguments:
+
+* _option_: one of following options:
+** _password_: password used to authenticate on _relay_ (option
+ _relay.network.password_ in WeeChat)
+** _compression_: compression type:
+*** _zlib_: enable _zlib_ compression for messages sent by _relay_
+*** _off_: disable compression
+
+[NOTE]
+Compression _zlib_ is enabled by default if _relay_ supports _zlib_ compression.
+
+Examples:
+
+----
+# initialize and use zlib compression by default (if WeeChat supports it)
+init password=mypass
+
+# initialize and disable compression
+init password=mypass,compression=off
+----
+
+[[command_hdata]]
+=== hdata
+
+Request a _hdata_.
+
+Syntax:
+
+----
+(id) hdata <path> [<keys>]
+----
+
+Arguments:
+
+* _path_: path to a hdata, with format: "hdata:pointer/var/var/.../var", the
+ last var is the hdata returned:
+** _hdata_: name of hdata
+** _pointer_: pointer ("0x12345") or list name (for example: "gui_buffers")
+ (count allowed, see below)
+** _var_: a variable name in parent hdata (previous name in path)
+ (count allowed, see below)
+* _keys_: comma-separated list of keys to return in hdata (if not specified, all
+ keys are returned, which is not recommended on large hdata structures)
+
+A count is allowed after pointer and variables, with format "(N)". Possible
+values are:
+
+* positive number: iterate using next element, N times
+* negative number: iterate using previous element, N times
+* _*_: iterate using next element, until end of list
+
+Examples:
+
+----
+# request all buffers, hdata of type "buffer" is returned
+# keys "number" and "name" are returned for each buffer
+hdata buffer:gui_buffers(*) number,name
+
+# request all lines of all buffers, hdata of type "line_data" is returned
+# all keys are returned
+hdata buffer:gui_buffers(*)/lines/first_line(*)/data
+
+# request full name of first buffer
+hdata buffer:gui_buffers full_name
+----
+
+[[command_info]]
+=== info
+
+Request an _info_.
+
+Syntax:
+
+----
+(id) info <name>
+----
+
+Arguments:
+
+* _name_: name of info to retrieve
+
+Example:
+
+----
+info version
+----
+
+[[command_infolist]]
+=== infolist
+
+Request an _infolist_.
+
+[IMPORTANT]
+Content of infolist is a duplication of actual data. Wherever possible, use
+command <<command_hdata,hdata>>, which is direct access to data (it is
+faster, uses less memory and returns smaller objects in message).
+
+Syntax:
+
+----
+(id) infolist <name> [<pointer> [<arguments>]]
+----
+
+Arguments:
+
+* _name_: name of infolist to retrieve
+* _pointer_: pointer (optional)
+* _arguments_: arguments (optional)
+
+Example:
+
+----
+infolist buffer
+----
+
+[[command_nicklist]]
+=== nicklist
+
+Request a _nicklist_, for one or all buffers.
+
+Syntax:
+
+----
+(id) nicklist [<buffer>]
+----
+
+Arguments:
+
+* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
+ _core.weechat_ or _irc.freenode.#weechat_)
+
+Examples:
+
+----
+# request nicklist for all buffers
+nicklist
+
+# request nicklist for irc.freenode.#weechat
+nicklist irc.freenode.#weechat
+----
+
+[[command_input]]
+=== input
+
+Send data to a buffer.
+
+Syntax:
+
+----
+input <buffer> <data>
+----
+
+Arguments:
+
+* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
+ _core.weechat_ or _irc.freenode.#weechat_)
+* _data_: data to send to buffer: if beginning by `/`, this will be executed as
+ a command on buffer, otherwise text is sent as input of buffer
+
+Examples:
+
+----
+input core.weechat /help filter
+input irc.freenode.#weechat hello!
+----
+
+[[command_sync]]
+=== sync
+
+_Updated in version 0.4.1._
+
+Synchronize one or more buffers, to get updates.
+
+[IMPORTANT]
+It is recommended to send this command immediately after you asked
+data for buffers (lines, ...). It can be send in same message (after a new
+line char: "\n").
+
+Syntax:
+
+----
+sync [<buffer>[,<buffer>...] <option>[,<option>...]]
+----
+
+Arguments:
+
+* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
+ _core.weechat_ or _irc.freenode.#weechat_); name "*" can be used to
+ specify all buffers
+* _options_: one of following keywords, separated by commas (default is
+ _buffers,upgrade,buffer,nicklist_ for "*" and _buffer,nicklist_ for a buffer):
+** _buffers_: receive signals about buffers (opened/closed, moved, renamed,
+ merged/unmerged, hidden/unhidden); this can be used only with name "*"
+ _(WeeChat ≥ 0.4.1)_
+** _upgrade_: receive signals about WeeChat upgrade (upgrade, upgrade ended);
+ this can be used only with name "*"
+ _(WeeChat ≥ 0.4.1)_
+** _buffer_: receive signals about buffer (new lines, type changed, title
+ changed, local variable added/removed, and same signals as _buffers_ for the
+ buffer) _(updated in version 0.4.1)_
+** _nicklist_: receive nicklist after changes
+
+Examples:
+
+----
+# synchronize all buffers with nicklist
+# (the 3 commands are equivalent, but the first one is recommended
+# for compatibility with future versions)
+sync
+sync *
+sync * buffers,upgrade,buffer,nicklist
+
+# synchronize core buffer
+sync core.buffer
+
+# synchronize #weechat channel, without nicklist
+sync irc.freenode.#weechat buffer
+
+# get general signals + all signals for #weechat channel
+sync * buffers,upgrade
+sync irc.freenode.#weechat
+----
+
+[[command_desync]]
+=== desync
+
+_Updated in version 0.4.1._
+
+Desynchronize one or more buffers, to stop updates.
+
+[NOTE]
+This will remove _options_ for buffers. If some options are still active for
+buffers, the client will still receive updates for these buffers.
+
+Syntax:
+
+----
+desync [<buffer>[,<buffer>...] <option>[,<option>...]]
+----
+
+Arguments:
+
+* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
+ _core.weechat_ or _irc.freenode.#weechat_); name "*" can be used to
+ specify all buffers
+* _options_: one of following keywords, separated by commas (default is
+ _buffers,upgrade,buffer,nicklist_ for "*" and _buffer,nicklist_ for a buffer);
+ see <<command_sync,command sync>> for values
+
+[NOTE]
+When using buffer "*", the other buffers synchronized (using a name) are kept. +
+So if you send: "sync *", then "sync irc.freenode.#weechat", then "desync *",
+the updates on #weechat channel will still be sent by WeeChat (you must remove
+it explicitly to stop updates).
+
+Examples:
+
+----
+# desynchronize all buffers
+# (the 3 commands are equivalent, but the first one is recommended
+# for compatibility with future versions)
+desync
+desync *
+desync * buffers,upgrade,buffer,nicklist
+
+# desynchronize nicklist for #weechat channel (keep buffer updates)
+desync irc.freenode.#weechat nicklist
+
+# desynchronize #weechat channel
+desync irc.freenode.#weechat
+----
+
+[[command_test]]
+=== test
+
+Test command: WeeChat will reply with various different objects.
+
+This command is useful to test the decoding of binary objects returned by
+WeeChat.
+
+[IMPORTANT]
+You must not use the pointer values returned by this command, they are not
+valid. This command must be used only to test decoding of a message sent by
+WeeChat.
+
+Syntax:
+
+----
+test
+----
+
+Example:
+
+----
+test
+----
+
+Returned objects (in this order):
+
+[width="80%",cols="^3,3m,5m",options="header"]
+|===
+| Type | Type (in message) | Value
+| char | chr | 65 ("A")
+| integer | int | 123456
+| integer | int | -123456
+| long | lon | 1234567890
+| long | lon | -1234567890
+| string | str | "a string"
+| string | str | ""
+| string | str | NULL
+| buffer | buf | "buffer"
+| buffer | buf | NULL
+| pointer | ptr | 0x1234abcd
+| pointer | ptr | NULL
+| time | tim | 1321993456
+| array of strings | arr str | [ "abc", "de" ]
+| array of integers | arr int | [ 123, 456, 789 ]
+|===
+
+[[command_ping]]
+=== ping
+
+_WeeChat ≥ 0.4.2._
+
+Send a ping to WeeChat which will reply with a message "_pong" and same arguments.
+
+This command is useful to test that connection with WeeChat is still alive and
+measure the response time.
+
+Syntax:
+
+----
+ping [<arguments>]
+----
+
+Example:
+
+----
+ping 1370802127000
+----
+
+[[command_quit]]
+=== quit
+
+Disconnect from _relay_.
+
+Syntax:
+
+----
+quit
+----
+
+Example:
+
+----
+quit
+----
+
+[[messages]]
+== Messages (relay → client)
+
+Messages are sent as binary data, using following format (with size in bytes):
+
+....
+┌────────╥─────────────╥────╥────────┬──────────╥───────╥────────┬──────────┐
+│ length ║ compression ║ id ║ type 1 │ object 1 ║ ... ║ type N │ object N │
+└────────╨─────────────╨────╨────────┴──────────╨───────╨────────┴──────────┘
+ └──────┘ └───────────┘ └──┘ └──────┘ └────────┘ └──────┘ └────────┘
+ 4 1 ?? 3 ?? 3 ??
+ └────────────────────┘ └──────────────────────────────────────────────────┘
+ header (5) compressed data (??)
+ └─────────────────────────────────────────────────────────────────────────┘
+ _length_ bytes
+....
+
+* _length_ (unsigned integer): number of bytes of whole message (including
+ this field)
+* _compression_ (byte): flag:
+** _0x00_: following data is not compressed
+** _0x01_: following data is compressed with _zlib_
+* _id_ (string): identifier sent by client (before command name); it can be
+ empty (string with zero length and no content) if no identifier was given in
+ command
+* _type_ (3 chars): a type: 3 letters (see table below)
+* _object_: an object (see table below)
+
+[[message_compression]]
+=== Compression
+
+If flag _compression_ is equal to 0x01, then *all* data after is compressed
+with _zlib_, and therefore must be uncompressed before being processed.
+
+[[message_identifier]]
+=== Identifier
+
+There are two types of identifiers (_id_):
+
+* _id_ sent by _client_: _relay_ will answer with same _id_ in its answer
+* _id_ of an event: on some events, _relay_ will send message to _client_ using
+ a specific _id_, beginning with underscore (see table below)
+
+WeeChat reserved identifiers:
+
+[width="100%",cols="5,5,3,4,7",options="header"]
+|===
+| Identifier | Received with _sync_ | Data sent |
+ Description | Recommended action in client
+
+| _buffer_opened | buffers / buffer | hdata: buffer |
+ Buffer opened | Open buffer
+
+| _buffer_type_changed | buffers / buffer | hdata: buffer |
+ Type of buffer changed | Change type of buffer
+
+| _buffer_moved | buffers / buffer | hdata: buffer |
+ Buffer moved | Move buffer
+
+| _buffer_merged | buffers / buffer | hdata: buffer |
+ Buffer merged | Merge buffer
+
+| _buffer_unmerged | buffers / buffer | hdata: buffer |
+ Buffer unmerged | Unmerge buffer
+
+| _buffer_hidden | buffers / buffer | hdata: buffer |
+ Buffer hidden | Hide buffer
+
+| _buffer_unhidden | buffers / buffer | hdata: buffer |
+ Buffer unhidden | Unhide buffer
+
+| _buffer_renamed | buffers / buffer | hdata: buffer |
+ Buffer renamed | Rename buffer
+
+| _buffer_title_changed | buffers / buffer | hdata: buffer |
+ Title of buffer changed | Change title of buffer
+
+| _buffer_localvar_added | buffers / buffer | hdata: buffer |
+ Local variable added | Add local variable in buffer
+
+| _buffer_localvar_changed | buffers / buffer | hdata: buffer |
+ Local variable changed | Change local variable in buffer
+
+| _buffer_localvar_removed | buffers / buffer | hdata: buffer |
+ Local variable removed | Remove local variable from buffer
+
+| _buffer_closing | buffers / buffer | hdata: buffer |
+ Buffer closing | Close buffer
+
+| _buffer_cleared | buffer | hdata: buffer |
+ Buffer cleared | Clear buffer
+
+| _buffer_line_added | buffer | hdata: line |
+ Line added in buffer | Display line in buffer
+
+| _nicklist | nicklist | hdata: nicklist_item |
+ Nicklist for a buffer | Replace nicklist
+
+| _nicklist_diff | nicklist | hdata: nicklist_item |
+ Nicklist diffs for a buffer | Update nicklist
+
+| _pong | (always) | string: ping arguments |
+ Answer to a "ping" | Measure response time
+
+| _upgrade | upgrade | (empty) |
+ WeeChat is upgrading | Desync from WeeChat (or disconnect)
+
+| _upgrade_ended | upgrade | (empty) |
+ Upgrade of WeeChat done | Sync/resync with WeeChat
+|===
+
+[[message_buffer_opened]]
+==== _buffer_opened
+
+This message is sent to the client when the signal "buffer_opened" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| short_name | string | Short name (example: _#weechat_)
+| nicklist | integer | 1 if buffer has a nicklist, otherwise 0
+| title | string | Buffer title
+| local_variables | hashtable | Local variables
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: channel _#weechat_ joined on freenode, new buffer
+_irc.freenode.#weechat_:
+
+[source,python]
+----
+id: '_buffer_opened'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'short_name': 'str', 'nicklist': 'int',
+ 'title': 'str', 'local_variables': 'htb', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x35a8a60']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ short_name: None
+ nicklist: 0
+ title: None
+ local_variables: {'plugin': 'irc', 'name': 'freenode.#weechat'}
+ prev_buffer: '0x34e7400'
+ next_buffer: '0x0'
+----
+
+[[message_buffer_moved]]
+==== _buffer_moved
+
+This message is sent to the client when the signal "buffer_moved" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: buffer _irc.freenode.#weechat_ moved to number 2:
+
+[source,python]
+----
+id: '_buffer_moved'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x34588c0']
+ number: 2
+ full_name: 'irc.freenode.#weechat'
+ prev_buffer: '0x347b9f0'
+ next_buffer: '0x3471bc0'
+----
+
+[[message_buffer_merged]]
+==== _buffer_merged
+
+This message is sent to the client when the signal "buffer_merged" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: buffer _irc.freenode.#weechat_ merged with buffer #2:
+
+[source,python]
+----
+id: '_buffer_merged'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4db4c00']
+ number: 2
+ full_name: 'irc.freenode.#weechat'
+ prev_buffer: '0x4cef9b0'
+ next_buffer: '0x0'
+----
+
+[[message_buffer_unmerged]]
+==== _buffer_unmerged
+
+This message is sent to the client when the signal "buffer_unmerged" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: buffer _irc.freenode.#weechat_ unmerged:
+
+[source,python]
+----
+id: '_buffer_unmerged'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4db4c00']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ prev_buffer: '0x4cef9b0'
+ next_buffer: '0x0'
+----
+
+[[message_buffer_hidden]]
+==== _buffer_hidden
+
+_WeeChat ≥ 1.0._
+
+This message is sent to the client when the signal "buffer_hidden" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: buffer _irc.freenode.#weechat_ hidden:
+
+[source,python]
+----
+id: '_buffer_hidden'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4db4c00']
+ number: 2
+ full_name: 'irc.freenode.#weechat'
+ prev_buffer: '0x4cef9b0'
+ next_buffer: '0x0'
+----
+
+[[message_buffer_unhidden]]
+==== _buffer_unhidden
+
+_WeeChat ≥ 1.0._
+
+This message is sent to the client when the signal "buffer_unhidden" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| prev_buffer | pointer | Pointer to previous buffer
+| next_buffer | pointer | Pointer to next buffer
+|===
+
+Example: buffer _irc.freenode.#weechat_ unhidden:
+
+[source,python]
+----
+id: '_buffer_unhidden'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'prev_buffer': 'ptr', 'next_buffer': 'ptr'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4db4c00']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ prev_buffer: '0x4cef9b0'
+ next_buffer: '0x0'
+----
+
+[[message_buffer_renamed]]
+==== _buffer_renamed
+
+This message is sent to the client when the signal "buffer_renamed" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| short_name | string | Short name (example: _#weechat_)
+| local_variables | hashtable | Local variables
+|===
+
+Example: private buffer renamed from _FlashCode_ to _Flash2_:
+
+[source,python]
+----
+id: '_buffer_renamed'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'short_name': 'str', 'local_variables': 'htb'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4df7b80']
+ number: 5
+ full_name: 'irc.freenode.Flash2'
+ short_name: 'Flash2'
+ local_variables: {'server': 'freenode', 'plugin': 'irc', 'type': 'private',
+ 'channel': 'FlashCode', 'nick': 'test', 'name': 'local.Flash2'}
+----
+
+[[message_buffer_title_changed]]
+==== _buffer_title_changed
+
+This message is sent to the client when the signal "buffer_title_changed" is
+sent by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| title | string | Buffer title
+|===
+
+Example: topic changed on channel _#weechat_:
+
+[source,python]
+----
+id: '_buffer_title_changed'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'title': 'str'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a715d0']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ title: 'Welcome on #weechat! https://weechat.org/'
+----
+
+[[message_buffer_cleared]]
+==== _buffer_cleared
+
+_WeeChat ≥ 1.0._
+
+This message is sent to the client when the signal "buffer_cleared" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+|===
+
+Example: buffer _irc.freenode.#weechat_ has been cleared:
+
+[source,python]
+----
+id: '_buffer_cleared'
+hda:
+ keys: {'number': 'int', 'full_name': 'str'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a715d0']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+----
+
+[[message_buffer_type_changed]]
+==== _buffer_type_changed
+
+This message is sent to the client when the signal "buffer_type_changed" is sent
+by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| type | integer | Buffer type: 0 = formatted (default), 1 = free content
+|===
+
+Example: type of buffer _script.scripts_ changed from formatted (0) to free
+content (1):
+
+[source,python]
+----
+id: '_buffer_type_changed'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'type': 'int'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x27c9a70']
+ number: 4
+ full_name: 'script.scripts'
+ type: 1
+----
+
+[[message_buffer_localvar_added]]
+==== _buffer_localvar_added
+
+This message is sent to the client when the signal "buffer_localvar_added" is
+sent by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| local_variables | hashtable | Local variables
+|===
+
+Example: local variable _test_ added in buffer _irc.freenode.#weechat_:
+
+[source,python]
+----
+id='_buffer_localvar_added', objects:
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'local_variables': 'htb'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a73de0']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ local_variables: {'server': 'freenode', 'test': 'value', 'plugin': 'irc',
+ 'type': 'channel', 'channel': '#weechat', 'nick': 'test',
+ 'name': 'freenode.#weechat'}
+----
+
+[[message_buffer_localvar_changed]]
+==== _buffer_localvar_changed
+
+This message is sent to the client when the signal "buffer_localvar_changed" is
+sent by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| local_variables | hashtable | Local variables
+|===
+
+Example: local variable _test_ updated in buffer _irc.freenode.#weechat_:
+
+[source,python]
+----
+id='_buffer_localvar_changed', objects:
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'local_variables': 'htb'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a73de0']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+ local_variables: {'server': 'local', 'test': 'value2', 'plugin': 'irc',
+ 'type': 'channel', 'channel': '#weechat', 'nick': 'test',
+ 'name': 'freenode.#weechat'}
+----
+
+[[message_buffer_localvar_removed]]
+==== _buffer_localvar_removed
+
+This message is sent to the client when the signal "buffer_localvar_removed" is
+sent by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+| local_variables | hashtable | Local variables
+|===
+
+Example: local variable _test_ removed from buffer _irc.freenode.#weechat_:
+
+[source,python]
+----
+id: '_buffer_localvar_removed'
+hda:
+ keys: {'number': 'int', 'full_name': 'str', 'local_variables': 'htb'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a73de0']
+ number: 3
+ full_name: 'irc.freenode.#prout'
+ local_variables: {'server': 'local', 'plugin': 'irc', 'type': 'channel',
+ 'channel': '#weechat', 'nick': 'test', 'name': 'freenode.#weechat'}
+----
+
+[[message_buffer_line_added]]
+==== _buffer_line_added
+
+This message is sent to the client when the signal "buffer_line_added" is sent
+by WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| buffer | pointer | Buffer pointer
+| date | time | Date of message
+| date_printed | time | Date when WeeChat displayed message
+| displayed | char | 1 if message is displayed, 0 if message is filtered (hidden)
+| highlight | char | 1 if line has a highlight, otherwise 0
+| tags_array | array of strings | List of tags for line
+| prefix | string | Prefix
+| message | string | Message
+|===
+
+Example: new message _hello!_ from nick _FlashCode_ on buffer _irc.freenode.#weechat_:
+
+[source,python]
+----
+id: '_buffer_line_added'
+hda:
+ keys: {'buffer': 'ptr', 'date': 'tim', 'date_printed': 'tim', 'displayed': 'chr',
+ 'highlight': 'chr', 'tags_array': 'arr', 'prefix': 'str', 'message': 'str'}
+ path: ['line_data']
+ item 1:
+ __path: ['0x4a49600']
+ buffer: '0x4a715d0'
+ date: 1362728993
+ date_printed: 1362728993
+ displayed: 1
+ highlight: 0
+ tags_array: ['irc_privmsg', 'notify_message', 'prefix_nick_142', 'nick_FlashCode', 'log1']
+ prefix: 'F06@F@00142FlashCode'
+ message: 'hello!'
+----
+
+[[message_buffer_closing]]
+==== _buffer_closing
+
+This message is sent to the client when the signal "buffer_closing" is sent by
+WeeChat.
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| number | integer | Buffer number (≥ 1)
+| full_name | string | Full name (example: _irc.freenode.#weechat_)
+|===
+
+Example: buffer _irc.freenode.#weechat_ is being closed by WeeChat:
+
+[source,python]
+----
+id: '_buffer_closing'
+hda:
+ keys: {'number': 'int', 'full_name': 'str'}
+ path: ['buffer']
+ item 1:
+ __path: ['0x4a715d0']
+ number: 3
+ full_name: 'irc.freenode.#weechat'
+----
+
+[[message_nicklist]]
+==== _nicklist
+
+This message is sent to the client when large updates are made on a nicklist
+(groups/nicks added/removed/changed). The message contains full nicklist.
+
+When small updates are made on a nicklist (for example just add one nick),
+another message with identifier __nicklist_diff_ is sent (see below).
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| group | char | 1 for a group, 0 for a nick
+| visible | char | 1 if group/nick is displayed, otherwise 0
+| level | integer | Level of group (0 for a nick)
+| name | string | Name of group/nick
+| color | string | Name color
+| prefix | string | Prefix (only for a nick)
+| prefix_color | string | Prefix color (only for a nick)
+|===
+
+Example: nicklist for buffer _irc.freenode.#weechat_:
+
+[source,python]
+----
+id: '_nicklist'
+hda:
+ keys: {'group': 'chr', 'visible': 'chr', 'level': 'int', 'name': 'str', 'color': 'str',
+ 'prefix': 'str', 'prefix_color': 'str'}
+ path: ['buffer', 'nicklist_item']
+ item 1:
+ __path: ['0x4a75cd0', '0x31e95d0']
+ group: 1
+ visible: 0
+ level: 0
+ name: 'root'
+ color: None
+ prefix: None
+ prefix_color: None
+ item 2:
+ __path: ['0x4a75cd0', '0x41247b0']
+ group: 1
+ visible: 1
+ level: 1
+ name: '000|o'
+ color: 'weechat.color.nicklist_group'
+ prefix: None
+ prefix_color: None
+ item 3:
+ __path: ['0x4a75cd0', '0x4a60d20']
+ group: 0
+ visible: 1
+ level: 0
+ name: 'FlashCode'
+ color: '142'
+ prefix: '@'
+ prefix_color: 'lightgreen'
+ item 4:
+ __path: ['0x4a75cd0', '0x4aafaf0']
+ group: 1
+ visible: 1
+ level: 1
+ name: '001|v'
+ color: 'weechat.color.nicklist_group'
+ prefix: None
+ prefix_color: None
+ item 5:
+ __path: ['0x4a75cd0', '0x4a48d80']
+ group: 1
+ visible: 1
+ level: 1
+ name: '999|...'
+ color: 'weechat.color.nicklist_group'
+ prefix: None
+ prefix_color: None
+ item 6:
+ __path: ['0x4a75cd0', '0x4a5f560']
+ group: 0
+ visible: 1
+ level: 0
+ name: 'test'
+ color: 'weechat.color.chat_nick_self'
+ prefix: ' '
+ prefix_color: ''
+----
+
+[[message_nicklist_diff]]
+==== _nicklist_diff
+
+_WeeChat ≥ 0.4.1._
+
+This message is sent to the client when small updates are made on a nicklist
+(groups/nicks added/removed/changed). The message contains nicklist differences
+(between old nicklist and current one).
+
+Data sent as hdata:
+
+[width="100%",cols="3m,2,10",options="header"]
+|===
+| Name | Type | Description
+| _diff | char | Type of diff (see below)
+| group | char | 1 for a group, 0 for a nick
+| visible | char | 1 if group/nick is displayed, otherwise 0
+| level | integer | Level of group (0 for a nick)
+| name | string | Name of group/nick
+| color | string | Name color
+| prefix | string | Prefix (only for a nick)
+| prefix_color | string | Prefix color (only for a nick)
+|===
+
+The value of __diff_ can be:
+
+* `^`: the parent group: group(s) or nick(s) after this one are related to this
+ group
+* `+`: group/nick added in the parent group
+* `-`: group/nick removed from the parent group
+* `*`: group/nick updated in the parent group
+
+Example: nick _master_ added in group _000|o_ (channel ops on an IRC channel),
+nicks _nick1_ and _nick2_ added in group _999|..._ (standard users on an IRC
+channel):
+
+[source,python]
+----
+id: '_nicklist_diff'
+hda:
+ keys: {'_diff': 'chr', 'group': 'chr', 'visible': 'chr', 'level': 'int', 'name': 'str',
+ 'color': 'str', 'prefix': 'str', 'prefix_color': 'str'}
+ path: ['buffer', 'nicklist_item']
+ item 1:
+ __path: ['0x46f2ee0', '0x343c9b0']
+ _diff: 94 ('^')
+ group: 1
+ visible: 1
+ level: 1
+ name: '000|o'
+ color: 'weechat.color.nicklist_group'
+ prefix: None
+ prefix_color: None
+ item 2:
+ __path: ['0x46f2ee0', '0x47e7f60']
+ _diff: 43 ('+')
+ group: 0
+ visible: 1
+ level: 0
+ name: 'master'
+ color: 'magenta'
+ prefix: '@'
+ prefix_color: 'lightgreen'
+ item 3:
+ __path: ['0x46f2ee0', '0x46b8e70']
+ _diff: 94 ('^')
+ group: 1
+ visible: 1
+ level: 1
+ name: '999|...'
+ color: 'weechat.color.nicklist_group'
+ prefix: None
+ prefix_color: None
+ item 4:
+ __path: ['0x46f2ee0', '0x3dba240']
+ _diff: 43 ('+')
+ group: 0
+ visible: 1
+ level: 0
+ name: 'nick1'
+ color: 'green'
+ prefix: ' '
+ prefix_color: ''
+ item 5:
+ __path: ['0x46f2ee0', '0x3c379d0']
+ _diff: 43 ('+')
+ group: 0
+ visible: 1
+ level: 0
+ name: 'nick2'
+ color: 'lightblue'
+ prefix: ' '
+ prefix_color: ''
+----
+
+[[message_pong]]
+==== _pong
+
+_WeeChat ≥ 0.4.2._
+
+This message is sent to the client when _relay_ receives a "ping" message.
+
+Data sent as string: arguments received in the "ping" message.
+
+The recommended action in client is to measure the response time and disconnect
+if it is high.
+
+[[message_upgrade]]
+==== _upgrade
+
+_WeeChat ≥ 0.3.8._
+
+This message is sent to the client when WeeChat is starting upgrade process.
+
+There is no data in the message.
+
+The recommended action in client is to desynchronize from WeeChat (send command
+_desync_), or to disconnect from WeeChat (because after upgrade, all pointers
+will change).
+
+[NOTE]
+During WeeChat upgrade, the socket remains opened (except if connection uses
+SSL).
+
+[[message_upgrade_ended]]
+==== _upgrade_ended
+
+_WeeChat ≥ 0.3.8._
+
+This message is sent to the client when WeeChat has finished the upgrade
+process.
+
+There is no data in the message.
+
+The recommended action in client is to resynchronize with WeeChat: resend all
+commands sent on startup after the _init_.
+
+[[objects]]
+=== Objects
+
+Objects are identified by 3 letters, called _type_. Following types are used:
+
+[width="100%",cols="^2m,5,10",options="header"]
+|===
+| Type | Value | Length
+| chr | Signed char | 1 byte
+| int | Signed integer | 4 bytes
+| lon | Signed long integer | 1 byte + length of integer as string
+| str | String | 4 bytes + length of string (without final _\0_)
+| buf | Buffer of bytes | 4 bytes + length of data
+| ptr | Pointer | 1 byte + length of pointer as string
+| tim | Time | 1 byte + length of time as string
+| htb | Hashtable | Variable
+| hda | Hdata content | Variable
+| inf | Info: name + content | Variable
+| inl | Infolist content | Variable
+| arr | Array of objects | 3 bytes (type) + number of objects + data
+|===
+
+[[object_char]]
+==== Char
+
+A signed char is stored as 1 byte.
+
+Example:
+
+....
+┌────┐
+│ 41 │ ────► 65 (0x41: "A")
+└────┘
+....
+
+[[object_integer]]
+==== Integer
+
+A signed integer is stored as 4 bytes, encoded as big-endian format (most
+significant byte first).
+
+Range: -2147483648 to 2147483647.
+
+Examples:
+
+....
+┌────┬────┬────┬────┐
+│ 00 │ 01 │ E2 │ 40 │ ────► 123456
+└────┴────┴────┴────┘
+
+┌────┬────┬────┬────┐
+│ FF │ FE │ 1D │ C0 │ ────► -123456
+└────┴────┴────┴────┘
+....
+
+[[object_long_integer]]
+==== Long integer
+
+A signed long integer is encoded as a string, with length on one byte.
+
+Range: -9223372036854775808 to 9223372036854775807.
+
+Examples:
+
+....
+┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
+│ 0A ║ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► 1234567890
+└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
+ └──┘ └───────────────────────────────────────────────┘
+length '1' '2' '3' '4' '5' '6' '7' '8' '9' '0'
+
+┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
+│ 0B ║ 2D │ 31 │ 32 │ 33 │ 34 │ 35 │ 36 │ 37 │ 38 │ 39 │ 30 │ ────► -1234567890
+└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
+ └──┘ └────────────────────────────────────────────────────┘
+length '-' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0'
+....
+
+[[object_string]]
+==== String
+
+A string is a length (integer on 4 bytes) + content of string (without final _\0_).
+
+Example:
+
+....
+┌────┬────┬────┬────╥────┬────┬────┬────┬────┐
+│ 00 │ 00 │ 00 │ 05 ║ 68 │ 65 │ 6C │ 6C │ 6F │ ────► "hello"
+└────┴────┴────┴────╨────┴────┴────┴────┴────┘
+ └─────────────────┘ └──────────────────────┘
+ length 'h' 'e' 'l' 'l' 'o'
+....
+
+An empty string has a length of zero:
+
+....
+┌────┬────┬────┬────┐
+│ 00 │ 00 │ 00 │ 00 │ ────► ""
+└────┴────┴────┴────┘
+ └─────────────────┘
+ length
+....
+
+A _NULL_ string (NULL pointer in C) has a length of -1:
+
+....
+┌────┬────┬────┬────┐
+│ FF │ FF │ FF │ FF │ ────► NULL
+└────┴────┴────┴────┘
+ └─────────────────┘
+ length
+....
+
+[[object_buffer]]
+==== Buffer
+
+Same format as <<object_string,string>>; content is just an array of bytes.
+
+[[object_pointer]]
+==== Pointer
+
+A pointer is encoded as string (hex), with length on one byte.
+
+Example:
+
+....
+┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┐
+│ 09 ║ 31 │ 61 │ 32 │ 62 │ 33 │ 63 │ 34 │ 64 │ 35 │ ────► 0x1a2b3c4d5
+└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┘
+ └──┘ └──────────────────────────────────────────┘
+length '1' 'a' '2' 'b' '3' 'c' '4' 'd' '5'
+....
+
+A _NULL_ pointer has a length of 1 with value 0:
+
+....
+┌────╥────┐
+│ 01 ║ 00 │ ────► NULL (0x0)
+└────╨────┘
+ └──┘ └──┘
+length 0
+....
+
+[[object_time]]
+==== Time
+
+A time (number of seconds) is encoded as a string, with length on one byte.
+
+Example:
+
+....
+┌────╥────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
+│ 0A ║ 31 │ 33 │ 32 │ 31 │ 39 │ 39 │ 33 │ 34 │ 35 │ 36 │ ────► 1321993456
+└────╨────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
+ └──┘ └───────────────────────────────────────────────┘
+length '1' '3' '2' '1' '9' '9' '3' '4' '5' '6'
+....
+
+[[object_hashtable]]
+==== Hashtable
+
+A hashtable contains type for keys, type for values, number of items in
+hashtable (integer on 4 bytes), and then keys and values of items.
+
+....
+┌───────────┬─────────────┬───────╥───────┬─────────╥─────╥───────┬─────────┐
+│ type_keys │ type_values │ count ║ key 1 │ value 1 ║ ... ║ key N │ value N │
+└───────────┴─────────────┴───────╨───────┴─────────╨─────╨───────┴─────────┘
+....
+
+Example:
+
+....
+┌─────┬─────┬───╥──────┬─────╥──────┬─────┐
+│ str │ str │ 2 ║ key1 │ abc ║ key2 │ def │ ────► { 'key1' => 'abc',
+└─────┴─────┴───╨──────┴─────╨──────┴─────┘ 'key2' => 'def' }
+ └───┘ └───┘ └─┘ └──────────┘ └──────────┘
+ type type count item 1 item 2
+ keys values
+....
+
+[[object_hdata]]
+==== Hdata
+
+A _hdata_ contains a path with hdata names, list of keys, number of set of
+objects, and then set of objects (path with pointers, then objects).
+
+....
+┌────────┬──────┬───────╥────────┬─────────────────────╥──
+│ h-path │ keys │ count ║ p-path │ value 1 ... value N ║ ...
+└────────┴──────┴───────╨────────┴─────────────────────╨──
+
+ ──╥────────┬─────────────────────╥─────┐
+ ... ║ p-path │ value 1 ... value N ║ ... │
+ ──╨────────┴─────────────────────╨─────┘
+....
+
+* _h-path_ (string): path used to reach hdata (example:
+ _buffer/lines/line/line_data_); the last element in path is the hdata returned
+* _keys_ (string): string with list of _key:type_ (separated by commas),
+ example: _number:int,name:str_
+* _count_ (integer): number of set of objects
+* _p-path_: path with pointers to objects (number of pointers here is number of
+ elements in path)
+* _values_: list of values (number of values is number of keys returned for
+ hdata)
+
+Example of hdata with two buffers (weechat core and freenode server) and two
+keys (_number_ and _full_name_):
+
+....
+# command
+hdata buffer:gui_buffers(*) number,full_name
+
+# response
+┌────────┬──────────────────────────┬───╥──
+│ buffer │ number:int,full_name:str │ 2 ║ ...
+└────────┴──────────────────────────┴───╨──
+ └──────┘ └────────────────────────┘ └─┘
+ h-path keys count
+
+ ──╥─────────┬───┬──────────────╥─────────┬───┬────────────────────┐
+ ... ║ 0x12345 │ 1 │ core.weechat ║ 0x6789a │ 2 │irc.server.freenode │
+ ──╨─────────┴───┴──────────────╨─────────┴───┴────────────────────┘
+ └──────────────────────────┘ └────────────────────────────────┘
+ buffer 1 buffer 2
+....
+
+Example of hdata with lines of core buffer:
+
+....
+# command
+hdata buffer:gui_buffers(*)/lines/first_line(*)/data
+
+# response
+┌─────────────────────────────┬─────┬────╥──
+│ buffer/lines/line/line_data │ ... │ 50 ║ ...
+└─────────────────────────────┴─────┴────╨──
+ └───────────────────────────┘ └───┘ └──┘
+ h-path (hdata names) keys count
+
+ ──╥───────────┬───────────┬───────────┬───────╥──
+ ... ║ 0x23cf970 │ 0x23cfb60 │ 0x23d5f40 │ ..... ║ ...
+ ──╨───────────┴───────────┴───────────┴───────╨──
+ └─────────────────────────────────┘ └─────┘
+ p-path (pointers) objects
+ └─────────────────────────────────────────┘
+ line 1
+
+ ──╥───────────┬───────────┬───────────┬───────╥──────────────┐
+ ... ║ 0x23cf970 │ 0x23cfb60 │ 0x23d6110 │ ..... ║ ............ │
+ ──╨───────────┴───────────┴───────────┴───────╨──────────────┘
+ └─────────────────────────────────┘ └─────┘
+ p-path (pointers) objects
+ └─────────────────────────────────────────┘ └────────────┘
+ line 2 lines 3-50
+....
+
+Example of hdata with nicklist:
+
+....
+# command
+nicklist
+
+# response
+┌───────────────────┬──
+│ buffer/nick_group │ ...
+└───────────────────┴──
+ └─────────────────┘
+ h-path
+
+ ──╥───────────────────────────────────────────────────────────┬────╥──
+ ... ║ group:chr,visible:chr,name:str,color:str,prefix:str,(...) │ 12 ║ ...
+ ──╨───────────────────────────────────────────────────────────┴────╨──
+ └─────────────────────────────────────────────────────────┘ └──┘
+ keys count
+
+ ──╥─────────┬─────────┬───┬───┬──────┬─┬─┬─┬───╥──
+ ... ║ 0x12345 │ 0x6789a │ 1 │ 0 │ root │ │ │ │ 0 ║ ...
+ ──╨─────────┴─────────┴───┴───┴──────┴─┴─┴─┴───╨──
+ └─────────────────┘ └──────────────────────┘
+ p-path objects
+ └──────────────────────────────────────────┘
+ group (nicklist root)
+
+ ──╥─────────┬─────────┬───┬───┬───────┬─┬─┬─┬───╥──
+ ... ║ 0x123cf │ 0x678d4 │ 1 │ 0 │ 000|o │ │ │ │ 1 ║ ...
+ ──╨─────────┴─────────┴───┴───┴───────┴─┴─┴─┴───╨──
+ └─────────────────┘ └───────────────────────┘
+ p-path objects
+ └───────────────────────────────────────────┘
+ group (channel ops)
+
+ ──╥─────────┬─────────┬───┬───┬──────────┬──────┬───┬────────────┬───╥──
+ ... ║ 0x128a7 │ 0x67ab2 │ 0 │ 1 │ ChanServ │ blue │ @ │ lightgreen │ 0 ║ ...
+ ──╨─────────┴─────────┴───┴───┴──────────┴──────┴───┴────────────┴───╨──
+ └─────────────────┘ └────────────────────────────────────────────┘
+ p-path objects
+ └────────────────────────────────────────────────────────────────┘
+ nick (@ChanServ)
+....
+
+[[object_info]]
+==== Info
+
+A _info_ contains a name and a value (both are strings).
+
+....
+┌──────┬───────┐
+│ name │ value │
+└──────┴───────┘
+....
+
+* _name_ (string): name of info
+* _value_ (string): value
+
+Example of info _version_:
+
+....
+┌─────────┬───────────────────┐
+│ version │ WeeChat 0.3.7-dev │
+└─────────┴───────────────────┘
+....
+
+[[object_infolist]]
+==== Infolist
+
+A _infolist_ contains a name, number of items, and then items (set of
+variables).
+
+....
+┌──────┬───────╥────────╥─────╥────────┐
+│ name │ count ║ item 1 ║ ... ║ item N │
+└──────┴───────╨────────╨─────╨────────┘
+....
+
+An item is:
+
+....
+┌───────╥────────┬────────┬─────────╥─────╥────────┬────────┬─────────┐
+│ count ║ name 1 │ type 1 │ value 1 ║ ... ║ name N │ type N │ value N │
+└───────╨────────┴────────┴─────────╨─────╨────────┴────────┴─────────┘
+....
+
+* _name_ (string): name of infolist (_buffer_, _window_, _bar_, ...)
+* _count_ (integer): number of items
+* _item_:
+** _count_: number of variables in item
+** _name_: name of variable
+** _type_: type of variable (_int_, _str_, ...)
+** _value_: value of variable
+
+Example of infolist with two buffers (weechat core and freenode server):
+
+....
+# command
+infolist buffer
+
+# response
+┌────────┬───╥────┬─────────┬─────┬─────────┬─────╥──
+│ buffer │ 2 ║ 42 │ pointer │ ptr │ 0x12345 │ ... ║ ...
+└────────┴───╨────┴─────────┴─────┴─────────┴─────╨──
+ └──────┘ └─┘ └──────────────────────────────────┘
+ name count item 1
+
+ ──╥────┬─────────┬─────┬─────────┬─────┐
+ ... ║ 42 │ pointer │ ptr │ 0x6789a │ ... │
+ ──╨────┴─────────┴─────┴─────────┴─────┘
+ └──────────────────────────────────┘
+ item 2
+....
+
+[[object_array]]
+==== Array
+
+An array is a type (3 bytes) + number of objects (integer on 4 bytes) + data.
+
+Example of array with two strings:
+
+....
+┌─────╥────┬────┬────┬────╥────┬────┬────┬────╥──
+│ str ║ 00 │ 00 │ 00 │ 02 ║ 00 │ 00 │ 00 │ 03 ║ ...
+└─────╨────┴────┴────┴────╨────┴────┴────┴────╨──
+ └───┘ └─────────────────┘ └─────────────────┘
+ type number of strings length
+
+ ──╥────┬────┬────╥────┬────┬────┬────╥────┬────┐
+ ... ║ 61 │ 62 │ 63 ║ 00 │ 00 │ 00 │ 02 ║ 64 │ 65 │ ────► [ "abc", "de" ]
+ ──╨────┴────┴────╨────┴────┴────┴────╨────┴────┘
+ └────────────┘ └─────────────────┘ └───────┘
+ 'a' 'b' 'c' length 'd' 'e'
+....
+
+Example of array with three integers:
+
+....
+┌─────╥────┬────┬────┬────╥────┬────┬────┬────╥──
+│ int ║ 00 │ 00 │ 00 │ 03 ║ 00 │ 00 │ 00 │ 7B ║ ...
+└─────╨────┴────┴────┴────╨────┴────┴────┴────╨──
+ └───┘ └─────────────────┘ └─────────────────┘
+ type number of integers 123 (0x7B)
+
+ ──╥────┬────┬────┬────╥────┬────┬────┬────┐
+ ... ║ 00 │ 00 │ 01 │ C8 ║ 00 │ 00 │ 03 │ 15 │ ────► [ 123, 456, 789 ]
+ ──╨────┴────┴────┴────╨────┴────┴────┴────┘
+ └─────────────────┘ └─────────────────┘
+ 456 (0x1C8) 789 (0x315)
+....
+
+A _NULL_ array:
+
+....
+┌─────╥────┬────┬────┬────┐
+│ str ║ 00 │ 00 │ 00 │ 00 │ ────► NULL
+└─────╨────┴────┴────┴────┘
+ └───┘ └─────────────────┘
+ type number of strings
+....
+
+[[typical_session]]
+== Typical session
+
+....
+ ┌────────┐ ┌───────┐ ┌─────────┐
+ │ Client ├ ─ ─ ─ ─(network)─ ─ ─ ─ ┤ Relay ├────────────────┤ WeeChat │
+ └────────┘ └───────┘ └─────────┘
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ open socket ║ add client ║
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ cmd: init password=xxx,... ║ init/allow client ║
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ cmd: hdata buffer ... ╟───────────────────────► ║
+ ║ sync ... ║ request hdata ║ read hdata
+ ║ ║ ║ values
+ ║ ║ ◄───────────────────────╢
+ ║ ◄───────────────────────────────╢ hdata ║
+ create ║ msg: hda buffer ║ ║
+ buffers ║ ║ ║
+ ║ ........ ║ ........ ║
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ cmd: input ... ╟───────────────────────► ║
+ ║ ║ send data to buffer ║ send data
+ ║ ║ ║ to buffer
+ ║ ........ ║ ........ ║
+ ║ ║ ║ signal
+ ║ ║ ◄───────────────────────╢ received
+ ║ ◄───────────────────────────────╢ signal XXX ║ (hooked by
+ update ║ msg: id: "_buffer_..." ║ ║ relay)
+ buffers ║ ║ ║
+ ║ ........ ║ ........ ║
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ cmd: ping ... ║ ║
+ ║ ║ ║
+ ║ ◄───────────────────────────────╢ ║
+ measure ║ msg: id: "_pong" ... ║ ║
+response ║ ║ ║
+ time ║ ........ ║ ........ ║
+ ║ ║ ║
+ ╟───────────────────────────────► ║ ║
+ ║ cmd: quit ║ disconnect client ║
+ ║ ║ ║
+....