1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-07 18:23:13 +02:00

relay: add command "completion" in weechat relay protocol (closes #1484)

This commit is contained in:
Sébastien Helleu
2020-04-28 11:15:30 +02:00
parent f2507a68a7
commit b6cc42cbf7
5 changed files with 599 additions and 33 deletions
+1
View File
@@ -29,6 +29,7 @@ New features::
* buflist: add options enable/disable/toggle in command /buflist
* buflist: evaluate option buflist.look.sort so that sort can be customized for each of the three buflist bar items (issue #1465)
* relay: add command "handshake" in weechat relay protocol and nonce to prevent replay attacks, add options relay.network.password_hash_algo, relay.network.password_hash_iterations, relay.network.nonce_size (issue #1474)
* relay: add command "completion" in weechat relay protocol to perform a completion on a string at a given position (issue #1484)
* relay: add option relay.network.auth_timeout
* relay: update default colors for client status
* relay: add status "waiting_auth" in irc and weechat protocols (issue #1358)
+141 -11
View File
@@ -86,17 +86,18 @@ List of available commands (detail in next chapters):
[width="100%",cols="^3m,14",options="header"]
|===
| Command | Description
| handshake | Handshake: prepare client authentication and set options, before _init_ command.
| init | Authenticate 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 | Description
| handshake | Handshake: prepare client authentication and set options, before _init_ command.
| init | Authenticate 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).
| completion | Request completion of a string.
| sync | Synchronize buffer(s): get updates for buffer(s).
| desync | Desynchronize buffer(s): stop updates for buffer(s).
| quit | Disconnect from _relay_.
|===
[[command_handshake]]
@@ -447,6 +448,135 @@ input core.weechat /help filter
input irc.freenode.#weechat hello!
----
[[command_completion]]
=== completion
_WeeChat ≥ 2.9._
Request completion of a string: list of possible words at a given position in
a string for a given buffer.
Syntax:
----
(id) completion <buffer> <position> [<data>]
----
Arguments:
* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
_core.weechat_ or _irc.freenode.#weechat_)
* _position_: position for completion in string (starts to 0);
if the value is -1, the position is the length of _data_ (so the completion
is made at the end of _data_)
* _data_: the input string; if not given, completion is performed on an empty
string
WeeChat replies with a hdata:
[width="100%",cols="3m,2,10",options="header"]
|===
| Name | Type | Description
| context | string | Completion context: "null" (no completion), "command", "command_arg", "auto".
| base_word | string | The base word used for completion.
| pos_start | integer | Index of first char to replace (starts to 0).
| pos_end | integer | Index of last char to replace (starts to 0).
| add_space | integer | 1 if a space must be added after words, 0 otherwise.
| list | array of strings | List of words found; empty if nothing was found to complete at asked position.
|===
[NOTE]
In case of error, for example invalid buffer or internal error on WeeChat side,
an empty hdata is returned.
Example: completion of a command argument:
----
(test) completion core.weechat -1 /help fi
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc842c0']
context: 'command_arg'
base_word: 'fi'
pos_start: 6
pos_end: 7
add_space: 0
list: ['fifo', 'fifo.file.enabled', 'fifo.file.path', 'filter']
----
Example: completion of a command in the middle of a word:
----
(test) completion core.weechat 5 /quernick
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'command'
base_word: 'quer'
pos_start: 1
pos_end: 4
add_space: 1
list: ['query']
----
Example: nothing to complete:
----
(test) completion core.weechat -1 abcdefghijkl
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'auto'
base_word: 'abcdefghijkl'
pos_start: 0
pos_end: 11
add_space: 1
list: []
----
Example: invalid buffer:
----
(test) completion buffer.does.not.exist -1 /help fi
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {}
path: ['completion']
----
[[command_sync]]
=== sync
+141 -11
View File
@@ -91,17 +91,18 @@ Liste des commandes disponibles (détail dans les chapitres suivants) :
[width="100%",cols="^3m,14",options="header"]
|===
| Commande | Description
| handshake | Poignée de main : préparer l'authentification du client et définir des options, avant la commande _init_.
| init | S'authentifier avec _relay_.
| hdata | Demander un _hdata_.
| info | Demander une _info_.
| infolist | Demander une _infolist_.
| nicklist | Demander une _nicklist_ (liste de pseudos).
| input | Envoyer des données à un tampon (texte ou commande).
| sync | Synchroniser un/des tampon(s) : recevoir les mises à jour pour le(s) tampon(s).
| desync | Désynchroniser un/des tampon(s) : stopper les mises à jour pour le(s) tampon(s).
| quit | Se déconnecter de _relay_.
| Commande | Description
| handshake | Poignée de main : préparer l'authentification du client et définir des options, avant la commande _init_.
| init | S'authentifier avec _relay_.
| hdata | Demander un _hdata_.
| info | Demander une _info_.
| infolist | Demander une _infolist_.
| nicklist | Demander une _nicklist_ (liste de pseudos).
| input | Envoyer des données à un tampon (texte ou commande).
| completion | Demander la complétion d'une chaîne.
| sync | Synchroniser un/des tampon(s) : recevoir les mises à jour pour le(s) tampon(s).
| desync | Désynchroniser un/des tampon(s) : stopper les mises à jour pour le(s) tampon(s).
| quit | Se déconnecter de _relay_.
|===
[[command_handshake]]
@@ -464,6 +465,135 @@ input core.weechat /help filter
input irc.freenode.#weechat bonjour !
----
[[command_completion]]
=== completion
_WeeChat ≥ 2.9._
Demander la complétion d'une chaîne : liste des mots possibles à une position
donnée dans la chaîne et sur un tampon donné.
Syntaxe :
----
(id) completion <tampon> <position> [<données>]
----
Paramètres :
* _tampon_ : pointeur (_0x12345_) ou nom complet du tampon (par exemple :
_core.weechat_ ou _irc.freenode.#weechat_)
* _position_ : position dans la chaîne pour la complétion (démarre à 0) ;
si la valeur est -1, la position est la longueur de _données_ (donc la
complétion se fait à la fin de _données_)
* _données_ : la chaîne en entrée ; si non donnée, la complétion est faite sur
une chaîne vide
WeeChat répond avec un hdata :
[width="100%",cols="3m,2,10",options="header"]
|===
| Nom | Type | Description
| context | chaîne | Contexte de complétion : "null" (pas de complétion), "command", "command_arg", "auto".
| base_word | chaîne | Le mot de base utilisé pour la complétion.
| pos_start | entier | Index du premier caractère à remplacer (démarre à 0).
| pos_end | entier | Index du dernier caractère à remplacer (démarre à 0).
| add_space | entier | 1 si un espace doit être ajouté après les mods, 0 sinon.
| list | tableau de chaînes | Liste des mots ; vide si rien n'a été trouvé pour compléter à la position demandée.
|===
[NOTE]
En cas d'erreur, par exemple un tampon invalide ou une erreur interne du côté
de WeeChat, un hdata vide est retourné.
Exemple : complétion d'un paramètre de commande :
----
(test) completion core.weechat -1 /help fi
----
Réponse :
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc842c0']
context: 'command_arg'
base_word: 'fi'
pos_start: 6
pos_end: 7
add_space: 0
list: ['fifo', 'fifo.file.enabled', 'fifo.file.path', 'filter']
----
Exemple : complétion d'une commande au milieu d'un mot :
----
(test) completion core.weechat 5 /quernick
----
Réponse :
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'command'
base_word: 'quer'
pos_start: 1
pos_end: 4
add_space: 1
list: ['query']
----
Exemple : rien à compléter :
----
(test) completion core.weechat -1 abcdefghijkl
----
Réponse :
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'auto'
base_word: 'abcdefghijkl'
pos_start: 0
pos_end: 11
add_space: 1
list: []
----
Exemple : tampon invalide :
----
(test) completion buffer.does.not.exist -1 /help fi
----
Réponse :
[source,python]
----
id: 'test'
hda:
keys: {}
path: ['completion']
----
[[command_sync]]
=== sync
+143 -11
View File
@@ -93,18 +93,20 @@ _リレー_ プラグインは _IRC プロキシ_ のように振舞います (
[width="100%",cols="^3m,14",options="header"]
|===
| コマンド | 説明
| コマンド | 説明
// TRANSLATION MISSING
| handshake | Handshake: prepare client authentication and set options, before _init_ command.
| init | _リレー_ 接続を初期化
| hdata | _hdata_ を要求
| info | _インフォ_ を要求
| infolist | _インフォリスト_ を要求
| nicklist | _ニックネームリスト_ を要求
| input | バッファにデータを送信 (テキストまたはコマンド)
| sync | バッファを同期: バッファの最新情報を取得
| desync | バッファを非同期: バッファの更新を止める
| quit | _リレー_ から切断
| handshake | Handshake: prepare client authentication and set options, before _init_ command.
| init | _リレー_ 接続を初期化
| hdata | _hdata_ を要求
| info | _インフォ_ を要求
| infolist | _インフォリスト_ を要求
| nicklist | _ニックネームリスト_ を要求
| input | バッファにデータを送信 (テキストまたはコマンド)
// TRANSLATION MISSING
| completion | Request completion of a string.
| sync | バッファを同期: バッファの最新情報を取得
| desync | バッファを非同期: バッファの更新を止める
| quit | _リレー_ から切断
|===
// TRANSLATION MISSING
@@ -462,6 +464,136 @@ input core.weechat /help filter
input irc.freenode.#weechat hello!
----
// TRANSLATION MISSING
[[command_completion]]
=== completion
_WeeChat ≥ 2.9._
Request completion of a string: list of possible words at a given position in
a string for a given buffer.
構文:
----
(id) completion <buffer> <position> [<data>]
----
引数:
* _buffer_: pointer (_0x12345_) or full name of buffer (for example:
_core.weechat_ or _irc.freenode.#weechat_)
* _position_: position for completion in string (starts to 0);
if the value is -1, the position is the length of _data_ (so the completion
is made at the end of _data_)
* _data_: the input string; if not given, completion is performed on an empty
string
WeeChat replies with a hdata:
[width="100%",cols="3m,2,10",options="header"]
|===
| Name | Type | Description
| context | string | Completion context: "null" (no completion), "command", "command_arg", "auto".
| base_word | string | The base word used for completion.
| pos_start | integer | Index of first char to replace (starts to 0).
| pos_end | integer | Index of last char to replace (starts to 0).
| add_space | integer | 1 if a space must be added after words, 0 otherwise.
| list | array of strings | List of words found; empty if nothing was found to complete at asked position.
|===
[NOTE]
In case of error, for example invalid buffer or internal error on WeeChat side,
an empty hdata is returned.
Example: completion of a command argument:
----
(test) completion core.weechat -1 /help fi
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc842c0']
context: 'command_arg'
base_word: 'fi'
pos_start: 6
pos_end: 7
add_space: 0
list: ['fifo', 'fifo.file.enabled', 'fifo.file.path', 'filter']
----
Example: completion of a command in the middle of a word:
----
(test) completion core.weechat 5 /quernick
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'command'
base_word: 'quer'
pos_start: 1
pos_end: 4
add_space: 1
list: ['query']
----
Example: nothing to complete:
----
(test) completion core.weechat -1 abcdefghijkl
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {'context': 'str', 'base_word': 'str', 'pos_start': 'int', 'pos_end': 'int', 'add_space': 'int', 'list': 'arr'}
path: ['completion']
item 1:
__path: ['0x55d0ccc88470']
context: 'auto'
base_word: 'abcdefghijkl'
pos_start: 0
pos_end: 11
add_space: 1
list: []
----
Example: invalid buffer:
----
(test) completion buffer.does.not.exist -1 /help fi
----
Response:
[source,python]
----
id: 'test'
hda:
keys: {}
path: ['completion']
----
[[command_sync]]
=== sync
@@ -664,6 +664,178 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(input)
return WEECHAT_RC_OK;
}
/*
* Callback for command "completion" (from client).
*
* Message looks like:
* completion core.weechat -1 /help fi
* input irc.freenode.#weechat 5 /quernick
* input 0x12345678 -1 nick
*/
RELAY_WEECHAT_PROTOCOL_CALLBACK(completion)
{
struct t_gui_buffer *ptr_buffer;
struct t_gui_completion *completion;
struct t_gui_completion_word *word;
struct t_hdata *ptr_hdata_completion, *ptr_hdata_completion_word;
struct t_arraylist *ptr_list;
struct t_relay_weechat_msg *msg;
char *error, *pos_data;
int i, position, length_data, context, pos_start, size;
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
completion = NULL;
/* return an empty hdata as error if there are not enough arguments */
if (argc < 2)
goto error;
ptr_buffer = relay_weechat_protocol_get_buffer (argv[0]);
if (!ptr_buffer)
{
if (weechat_relay_plugin->debug >= 1)
{
weechat_printf (NULL,
_("%s: invalid buffer in message: \"%s %s\""),
RELAY_PLUGIN_NAME,
command,
argv[0]);
}
goto error;
}
error = NULL;
position = (int)strtol (argv[1], &error, 10);
if (!error || error[0])
goto error;
pos_data = strchr (argv_eol[1], ' ');
if (pos_data)
pos_data++;
length_data = strlen ((pos_data) ? pos_data : "");
if ((position < 0) || (position > length_data))
position = length_data;
completion = weechat_completion_new (ptr_buffer);
if (!completion)
goto error;
if (!weechat_completion_search (completion,
(pos_data) ? pos_data : "",
position,
1))
{
goto error;
}
ptr_hdata_completion = weechat_hdata_get ("completion");
if (!ptr_hdata_completion)
goto error;
ptr_hdata_completion_word = weechat_hdata_get ("completion_word");
if (!ptr_hdata_completion_word)
goto error;
ptr_list = weechat_hdata_pointer (ptr_hdata_completion, completion, "list");
if (!ptr_list)
goto error;
msg = relay_weechat_msg_new (id);
if (msg)
{
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA);
relay_weechat_msg_add_string (msg, "completion");
relay_weechat_msg_add_string (msg,
"context:str,"
"base_word:str,"
"pos_start:int,"
"pos_end:int,"
"add_space:int,"
"list:arr");
relay_weechat_msg_add_int (msg, 1); /* count */
relay_weechat_msg_add_pointer (msg, completion);
/* context */
context = weechat_hdata_integer (ptr_hdata_completion, completion,
"context");
switch (context)
{
case 0:
relay_weechat_msg_add_string (msg, "null");
break;
case 1:
relay_weechat_msg_add_string (msg, "command");
break;
case 2:
relay_weechat_msg_add_string (msg, "command_arg");
break;
default:
relay_weechat_msg_add_string (msg, "auto");
break;
}
/* base_word */
relay_weechat_msg_add_string (
msg,
weechat_hdata_string (ptr_hdata_completion,
completion, "base_word"));
/* pos_start */
pos_start = weechat_hdata_integer (ptr_hdata_completion,
completion, "position_replace");
relay_weechat_msg_add_int (msg, pos_start);
/* pos_end */
relay_weechat_msg_add_int (
msg,
(position > pos_start) ? position - 1 : position);
/* add_space */
relay_weechat_msg_add_int (
msg,
weechat_hdata_integer (ptr_hdata_completion,
completion, "add_space"));
/* list */
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_STRING);
size = weechat_arraylist_size (ptr_list);
relay_weechat_msg_add_int (msg, size);
for (i = 0; i < size; i++)
{
word = (struct t_gui_completion_word *)weechat_arraylist_get (
ptr_list, i);
relay_weechat_msg_add_string (
msg,
weechat_hdata_string (ptr_hdata_completion_word, word, "word"));
}
/* send message */
relay_weechat_msg_send (client, msg);
relay_weechat_msg_free (msg);
}
weechat_completion_free (completion);
return WEECHAT_RC_OK;
error:
if (completion)
weechat_completion_free (completion);
msg = relay_weechat_msg_new (id);
if (msg)
{
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HDATA);
relay_weechat_msg_add_string (msg, "completion");
relay_weechat_msg_add_string (msg, NULL); /* keys */
relay_weechat_msg_add_int (msg, 0); /* count */
/* send message */
relay_weechat_msg_send (client, msg);
relay_weechat_msg_free (msg);
}
return WEECHAT_RC_OK;
}
/*
* Callback for signals "buffer_*".
*/
@@ -1565,6 +1737,7 @@ relay_weechat_protocol_recv (struct t_relay_client *client, const char *data)
{ "infolist", &relay_weechat_protocol_cb_infolist },
{ "nicklist", &relay_weechat_protocol_cb_nicklist },
{ "input", &relay_weechat_protocol_cb_input },
{ "completion", &relay_weechat_protocol_cb_completion },
{ "sync", &relay_weechat_protocol_cb_sync },
{ "desync", &relay_weechat_protocol_cb_desync },
{ "test", &relay_weechat_protocol_cb_test },