1 /*
2 * cmd_defs.c
3 * vim: expandtab:ts=4:sts=4:sw=4
4 *
5 * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
6 * Copyright (C) 2019 Michael Vetter <jubalh@iodoru.org>
7 *
8 * This file is part of Profanity.
9 *
10 * Profanity is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Profanity is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
22 *
23 * In addition, as a special exception, the copyright holders give permission to
24 * link the code of portions of this program with the OpenSSL library under
25 * certain conditions as described in each individual source file, and
26 * distribute linked combinations including the two.
27 *
28 * You must obey the GNU General Public License in all respects for all of the
29 * code used other than OpenSSL. If you modify file(s) with this exception, you
30 * may extend this exception to your version of the file(s), but you are not
31 * obligated to do so. If you do not wish to do so, delete this exception
32 * statement from your version. If you delete this exception statement from all
33 * source files in the program, then also delete it here.
34 *
35 */
36
37 #include "config.h"
38
39 #include <assert.h>
40 #include <errno.h>
41 #include <limits.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <libgen.h>
46 #include <dirent.h>
47 #include <sys/types.h>
48
49 #include <glib.h>
50
51 #include "profanity.h"
52 #include "log.h"
53 #include "common.h"
54 #include "command/cmd_defs.h"
55 #include "command/cmd_funcs.h"
56 #include "command/cmd_ac.h"
57 #include "config/accounts.h"
58 #include "config/preferences.h"
59 #include "config/theme.h"
60 #include "config/tlscerts.h"
61 #include "config/scripts.h"
62 #include "plugins/plugins.h"
63 #include "tools/autocomplete.h"
64 #include "tools/parser.h"
65 #include "ui/ui.h"
66 #include "ui/window_list.h"
67 #include "xmpp/xmpp.h"
68 #include "xmpp/contact.h"
69 #include "xmpp/roster_list.h"
70 #include "xmpp/jid.h"
71 #include "xmpp/chat_session.h"
72 #include "xmpp/muc.h"
73
74 #ifdef HAVE_LIBOTR
75 #include "otr/otr.h"
76 #endif
77
78 #ifdef HAVE_LIBGPGME
79 #include "pgp/gpg.h"
80 #endif
81
82 #define CMD_TAG_CHAT "chat"
83 #define CMD_TAG_GROUPCHAT "groupchat"
84 #define CMD_TAG_ROSTER "roster"
85 #define CMD_TAG_PRESENCE "presence"
86 #define CMD_TAG_CONNECTION "connection"
87 #define CMD_TAG_DISCOVERY "discovery"
88 #define CMD_TAG_UI "ui"
89 #define CMD_TAG_PLUGINS "plugins"
90
91 #define CMD_MAINFUNC(func) func,
92 #define CMD_NOMAINFUNC NULL,
93 #define CMD_SUBFUNCS(...) { __VA_ARGS__, { NULL, NULL } },
94 #define CMD_NOSUBFUNCS { { NULL, NULL } },
95
96 #define CMD_NOTAGS \
97 { \
98 { NULL },
99 #define CMD_TAGS(...) \
100 { \
101 { __VA_ARGS__, NULL },
102 #define CMD_SYN(...) { __VA_ARGS__, NULL },
103 #define CMD_DESC(desc) desc,
104 #define CMD_NOARGS { { NULL, NULL } },
105 #define CMD_ARGS(...) { __VA_ARGS__, { NULL, NULL } },
106 #define CMD_NOEXAMPLES \
107 { \
108 NULL \
109 } \
110 }
111 #define CMD_EXAMPLES(...) \
112 { \
113 __VA_ARGS__, NULL \
114 } \
115 }
116
117 GHashTable* commands = NULL;
118
119 static gboolean _cmd_has_tag(Command* pcmd, const char* const tag);
120
121 /*
122 * Command list
123 */
124
125 // clang-format off
126 static struct cmd_t command_defs[] = {
127 { "/help",
128 parse_args_with_freetext, 0, 2, NULL,
129 CMD_NOSUBFUNCS
130 CMD_MAINFUNC(cmd_help)
131 CMD_NOTAGS
132 CMD_SYN(
133 "/help [<area>|<command>|search_all|search_any] [<search_terms>]")
134 CMD_DESC(
135 "Help on using Profanity. Passing no arguments list help areas. "
136 "For command help, optional arguments are shown using square brackets, "
137 "arguments representing variables rather than a literal name are surrounded by angle brackets. "
138 "Arguments that may be one of a number of values are separated by a pipe "
139 "e.g. val1|val2|val3.")
140 CMD_ARGS(
141 { "<area>", "Summary help for commands in a certain area of functionality." },
142 { "<command>", "Full help for a specific command, for example '/help connect'." },
143 { "search_all <search_terms>", "Search commands for returning matches that contain all of the search terms." },
144 { "search_any <search_terms>", "Search commands for returning matches that contain any of the search terms." })
145 CMD_EXAMPLES(
146 "/help search_all presence online",
147 "/help commands",
148 "/help presence",
149 "/help who")
150 },
151
152 { "/about",
153 parse_args, 0, 0, NULL,
154 CMD_NOSUBFUNCS
155 CMD_MAINFUNC(cmd_about)
156 CMD_NOTAGS
157 CMD_SYN(
158 "/about")
159 CMD_DESC(
160 "Show version and license information.")
161 CMD_NOARGS
162 CMD_NOEXAMPLES
163 },
164
165 { "/connect",
166 parse_args, 0, 7, NULL,
167 CMD_NOSUBFUNCS
168 CMD_MAINFUNC(cmd_connect)
169 CMD_TAGS(
170 CMD_TAG_CONNECTION)
171 CMD_SYN(
172 "/connect [<account>]",
173 "/connect <account> [server <server>] [port <port>] [tls force|allow|trust|legacy|disable] [auth default|legacy]")
174 CMD_DESC(
175 "Login to a chat service. "
176 "If no account is specified, the default is used if one is configured. "
177 "A local account is created with the JID as it's name if it doesn't already exist.")
178 CMD_ARGS(
179 { "<account>", "The local account you wish to connect with, or a JID if connecting for the first time." },
180 { "server <server>", "Supply a server if it is different to the domain part of your JID." },
181 { "port <port>", "The port to use if different to the default (5222, or 5223 for SSL)." },
182 { "tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." },
183 { "tls allow", "Use TLS for the connection if it is available." },
184 { "tls trust", "Force TLS connection and trust server's certificate." },
185 { "tls legacy", "Use legacy TLS for the connection. It means server doesn't support STARTTLS and TLS is forced just after TCP connection is established." },
186 { "tls disable", "Disable TLS for the connection." },
187 { "auth default", "Default authentication process." },
188 { "auth legacy", "Allow legacy authentication." })
189 CMD_EXAMPLES(
190 "/connect",
191 "/connect odin@valhalla.edda",
192 "/connect odin@valhalla.edda server talk.google.com",
193 "/connect freyr@vanaheimr.edda port 5678",
194 "/connect me@localhost.test.org server 127.0.0.1 tls disable",
195 "/connect me@chatty server chatty.com port 5443")
196 },
197
198 { "/tls",
199 parse_args, 1, 3, NULL,
200 CMD_SUBFUNCS(
201 { "certpath", cmd_tls_certpath },
202 { "trust", cmd_tls_trust },
203 { "trusted", cmd_tls_trusted },
204 { "revoke", cmd_tls_revoke },
205 { "cert", cmd_tls_cert })
206 CMD_NOMAINFUNC
207 CMD_TAGS(
208 CMD_TAG_CONNECTION,
209 CMD_TAG_UI)
210 CMD_SYN(
211 "/tls allow",
212 "/tls always",
213 "/tls deny",
214 "/tls cert [<fingerprint>]",
215 "/tls trust",
216 "/tls trusted",
217 "/tls revoke <fingerprint>",
218 "/tls certpath",
219 "/tls certpath set <path>",
220 "/tls certpath clear",
221 "/tls certpath default")
222 CMD_DESC(
223 "Handle TLS certificates. ")
224 CMD_ARGS(
225 { "allow", "Allow connection to continue with TLS certificate." },
226 { "always", "Always allow connections with TLS certificate." },
227 { "deny", "Abort connection." },
228 { "cert", "Show the current TLS certificate." },
229 { "cert <fingerprint>", "Show details of trusted certificate." },
230 { "trust", "Add the current TLS certificate to manually trusted certificates." },
231 { "trusted", "List summary of manually trusted certificates (with '/tls always' or '/tls trust')." },
232 { "revoke <fingerprint>", "Remove a manually trusted certificate." },
233 { "certpath", "Show the trusted certificate path." },
234 { "certpath set <path>", "Specify filesystem path containing trusted certificates." },
235 { "certpath clear", "Clear the trusted certificate path." },
236 { "certpath default", "Use default system certificate path, if it can be found." })
237 CMD_NOEXAMPLES
238 },
239
240 { "/disconnect",
241 parse_args, 0, 0, NULL,
242 CMD_NOSUBFUNCS
243 CMD_MAINFUNC(cmd_disconnect)
244 CMD_TAGS(
245 CMD_TAG_CONNECTION)
246 CMD_SYN(
247 "/disconnect")
248 CMD_DESC(
249 "Disconnect from the current chat service.")
250 CMD_NOARGS
251 CMD_NOEXAMPLES
252 },
253
254 { "/msg",
255 parse_args_with_freetext, 1, 2, NULL,
256 CMD_NOSUBFUNCS
257 CMD_MAINFUNC(cmd_msg)
258 CMD_TAGS(
259 CMD_TAG_CHAT)
260 CMD_SYN(
261 "/msg <contact> [<message>]",
262 "/msg <nick> [<message>]")
263 CMD_DESC(
264 "Send a one to one chat message, or a private message to a chat room occupant. "
265 "If the message is omitted, a new chat window will be opened without sending a message. "
266 "Use quotes if the nickname includes spaces.")
267 CMD_ARGS(
268 { "<contact>", "Open chat window with contact, by JID or nickname." },
269 { "<contact> [<message>]", "Send message to contact, by JID or nickname." },
270 { "<nick>", "Open private chat window with chat room occupant." },
271 { "<nick> [<message>]", "Send a private message to a chat room occupant." })
272 CMD_EXAMPLES(
273 "/msg thor@valhalla.edda Hey, here's a message!",
274 "/msg heimdall@valhalla.edda",
275 "/msg Thor Here is a private message",
276 "/msg \"My Friend\" Hi, how are you?")
277 },
278
279 { "/roster",
280 parse_args_with_freetext, 0, 4, NULL,
281 CMD_SUBFUNCS(
282 { "group", cmd_group })
283 CMD_MAINFUNC(cmd_roster)
284 CMD_TAGS(
285 CMD_TAG_ROSTER,
286 CMD_TAG_UI)
287 CMD_SYN(
288 "/roster",
289 "/roster online",
290 "/roster show [offline|resource|presence|status|empty|priority|contacts|rooms]",
291 "/roster hide [offline|resource|presence|status|empty|priority|contacts|rooms]",
292 "/roster by group|presence|none",
293 "/roster count unread|items|off",
294 "/roster count zero on|off",
295 "/roster color on|off",
296 "/roster order name|presence",
297 "/roster unread before|after|off",
298 "/roster room char <char>|none",
299 "/roster room private char <char>|none",
300 "/roster room position first|last",
301 "/roster room by service|none",
302 "/roster room order name|unread",
303 "/roster room unread before|after|off",
304 "/roster room show server",
305 "/roster room hide server",
306 "/roster room use name|jid",
307 "/roster private room|group|off",
308 "/roster private char <char>|none",
309 "/roster header char <char>|none",
310 "/roster presence indent <indent>",
311 "/roster contact char <char>|none",
312 "/roster contact indent <indent>",
313 "/roster resource char <char>|none",
314 "/roster resource indent <indent>",
315 "/roster resource join on|off",
316 "/roster size <percent>",
317 "/roster wrap on|off",
318 "/roster add <jid> [<nick>]",
319 "/roster remove <jid>",
320 "/roster remove_all contacts",
321 "/roster nick <jid> <nick>",
322 "/roster clearnick <jid>",
323 "/roster group",
324 "/roster group show <group>",
325 "/roster group add <group> <contat>",
326 "/roster group remove <group> <contact>")
327 CMD_DESC(
328 "Manage your roster, and roster display settings. "
329 "Passing no arguments lists all contacts in your roster.")
330 CMD_ARGS(
331 { "online", "Show all online contacts in console." },
332 { "show", "Show the roster panel." },
333 { "show offline", "Show offline contacts in roster panel." },
334 { "show resource", "Show contact's connected resources in roster panel." },
335 { "show presence", "Show contact's presence in roster panel." },
336 { "show status", "Show contact's status message in roster panel." },
337 { "show empty", "Show empty groups in roster panel." },
338 { "show priority", "Show resource priority in roster panel." },
339 { "show contacts", "Show contacts in roster panel." },
340 { "show rooms", "Show chat rooms in roster panel." },
341 { "hide", "Hide the roster panel." },
342 { "hide offline", "Hide offline contacts in roster panel." },
343 { "hide resource", "Hide contact's connected resources in roster panel." },
344 { "hide presence", "Hide contact's presence in roster panel." },
345 { "hide status", "Hide contact's status message in roster panel." },
346 { "hide empty", "Hide empty groups in roster panel." },
347 { "hide priority", "Hide resource priority in roster panel." },
348 { "hide contacts", "Hide contacts in roster panel." },
349 { "hide rooms", "Hide chat rooms in roster panel." },
350 { "by group", "Group contacts in roster panel by roster group." },
351 { "by presence", "Group contacts in roster panel by presence." },
352 { "by none", "No grouping in roster panel." },
353 { "count unread", "Show unread message count with roster headers." },
354 { "count items", "Show item count with roster headers." },
355 { "count off", "Do not show any count with roster headers." },
356 { "count zero on", "Show roster header count when 0." },
357 { "count zero off", "Hide roster header count when 0." },
358 { "color on", "Enable generated color names (XEP-0392)" },
359 { "color off", "Disable generated color names (XEP-0392)" },
360 { "order name", "Order roster contacts by name only." },
361 { "order presence", "Order roster contacts by presence, and then by name." },
362 { "unread before", "Show unread message count before contact." },
363 { "unread after", "Show unread message count after contact." },
364 { "unread off", "Do not show unread message count for contacts." },
365 { "room char <char>", "Prefix rooms with specified character." },
366 { "room char none", "Remove room character prefix." },
367 { "room private char <char>", "Prefix private room chat with specified character when displayed with room." },
368 { "room private char none", "Remove private room chat character prefix when displayed with room." },
369 { "room position first", "Show rooms first in roster." },
370 { "room position last", "Show rooms last in roster." },
371 { "room by service", "Group rooms by chat service." },
372 { "room by none", "Do not group rooms." },
373 { "room order name", "Order rooms by name." },
374 { "room order unread", "Order rooms by unread messages, and then by name." },
375 { "room unread before", "Show unread message count before room." },
376 { "room unread after", "Show unread message count after room." },
377 { "room unread off", "Do not show unread message count for rooms." },
378 { "room show server", "Show the conference server with room JIDs." },
379 { "room hide server", "Do not show the conference server with room JIDs." },
380 { "room use name", "Use the MUC name as room name." },
381 { "room use jid", "Use the JID as room name." },
382 { "private room", "Show room private chats with the room." },
383 { "private group", "Show room private chats as a separate roster group." },
384 { "private off", "Do not show room private chats." },
385 { "private char <char>", "Prefix private room chats with specified character when displayed in separate group." },
386 { "private char none", "Remove private room chat character prefix." },
387 { "header char <char>", "Prefix roster headers with specified character." },
388 { "header char none", "Remove roster header character prefix." },
389 { "contact char <char>", "Prefix roster contacts with specified character." },
390 { "contact char none", "Remove roster contact character prefix." },
391 { "contact indent <indent>", "Indent contact line by <indent> spaces (0 to 10)." },
392 { "resource char <char>", "Prefix roster resources with specified character." },
393 { "resource char none", "Remove roster resource character prefix." },
394 { "resource indent <indent>", "Indent resource line by <indent> spaces (0 to 10)." },
395 { "resource join on|off", "Join resource with previous line when only one available resource." },
396 { "presence indent <indent>", "Indent presence line by <indent> spaces (-1 to 10), a value of -1 will show presence on the previous line." },
397 { "size <percent>", "Percentage of the screen taken up by the roster (1-99)." },
398 { "wrap on|off", "Enable or disable line wrapping in roster panel." },
399 { "add <jid> [<nick>]", "Add a new item to the roster." },
400 { "remove <jid>", "Removes an item from the roster." },
401 { "remove_all contacts", "Remove all items from roster." },
402 { "nick <jid> <nick>", "Change a contacts nickname." },
403 { "clearnick <jid>", "Removes the current nickname." },
404 { "group show <group>", "List all roster items in a group." },
405 { "group add <group> <contact>", "Add a contact to a group." },
406 { "group remove <group> <contact>", "Remove a contact from a group." })
407 CMD_EXAMPLES(
408 "/roster",
409 "/roster add odin@valhalla.edda",
410 "/roster add odin@valhalla.edda Allfather",
411 "/roster remove loki@ownserver.org",
412 "/roster nick odin@valhalla.edda \"All Father\"",
413 "/roster clearnick thor@valhalla.edda",
414 "/roster size 15",
415 "/roster group",
416 "/roster group show friends",
417 "/roster group add friends fenris@ownserver.org",
418 "/roster group add family Brother",
419 "/roster group remove colleagues boss@work.com")
420 },
421
422 { "/blocked",
423 parse_args_with_freetext, 0, 3, NULL,
424 CMD_NOSUBFUNCS
425 CMD_MAINFUNC(cmd_blocked)
426 CMD_TAGS(
427 CMD_TAG_ROSTER,
428 CMD_TAG_CHAT)
429 CMD_SYN(
430 "/blocked",
431 "/blocked add [<jid>]",
432 "/blocked report-abuse [<jid>] [<message>]",
433 "/blocked report-spam [<jid>] [<message>]",
434 "/blocked remove <jid>")
435 CMD_DESC(
436 "Manage blocked users (XEP-0191), calling with no arguments shows the current list of blocked users. "
437 "To blog a certain user in a MUC use the following as jid: room@conference.example.org/spammy-user"
438 "It is also possible to block and report (XEP-0377) a user with the report-abuse and report-spam commands.")
439 CMD_ARGS(
440 { "add [<jid>]", "Block the specified Jabber ID. If in a chat window and no jid is specified, the current recipient will be blocked." },
441 { "remove <jid>", "Remove the specified Jabber ID from the blocked list." },
442 { "report-abuse <jid> [<message>]", "Report the jid as abuse with an optional message to the service operator." },
443 { "report-spam <jid> [<message>]", "Report the jid as spam with an optional message to the service operator." })
444 CMD_EXAMPLES(
445 "/blocked add hel@helheim.edda",
446 "/blocked report-spam hel@helheim.edda Very annoying guy",
447 "/blocked add profanity@rooms.dismail.de/spammy-user")
448 },
449
450 { "/info",
451 parse_args, 0, 1, NULL,
452 CMD_NOSUBFUNCS
453 CMD_MAINFUNC(cmd_info)
454 CMD_TAGS(
455 CMD_TAG_ROSTER,
456 CMD_TAG_CHAT,
457 CMD_TAG_GROUPCHAT)
458 CMD_SYN(
459 "/info",
460 "/info <contact>|<nick>")
461 CMD_DESC(
462 "Show information about a contact, room, or room member. "
463 "Passing no argument in a chat window will use the current recipient. "
464 "Passing no argument in a chat room will display information about the room.")
465 CMD_ARGS(
466 { "<contact>", "The contact you wish to view information about." },
467 { "<nick>", "When in a chat room, the occupant you wish to view information about." })
468 CMD_EXAMPLES(
469 "/info thor@aasgard.server.org",
470 "/info heimdall")
471 },
472
473 { "/caps",
474 parse_args, 0, 1, NULL,
475 CMD_NOSUBFUNCS
476 CMD_MAINFUNC(cmd_caps)
477 CMD_TAGS(
478 CMD_TAG_DISCOVERY,
479 CMD_TAG_CHAT,
480 CMD_TAG_GROUPCHAT)
481 CMD_SYN(
482 "/caps",
483 "/caps <fulljid>|<nick>")
484 CMD_DESC(
485 "Find out a contacts, or room members client software capabilities. "
486 "If in private chat initiated from a chat room, no parameter is required.")
487 CMD_ARGS(
488 { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see capabilities." },
489 { "<nick>", "If in a chat room, nickname for which you wish to see capabilities." })
490 CMD_EXAMPLES(
491 "/caps ran@cold.sea.org/laptop",
492 "/caps ran@cold.sea.org/phone",
493 "/caps aegir")
494 },
495
496 { "/software",
497 parse_args, 0, 1, NULL,
498 CMD_NOSUBFUNCS
499 CMD_MAINFUNC(cmd_software)
500 CMD_TAGS(
501 CMD_TAG_DISCOVERY,
502 CMD_TAG_CHAT,
503 CMD_TAG_GROUPCHAT)
504 CMD_SYN(
505 "/software",
506 "/software <fulljid>|<nick>")
507 CMD_DESC(
508 "Find out a contact, or room members software version information. "
509 "If in private chat initiated from a chat room, no parameter is required. "
510 "If the contact's software does not support software version requests, nothing will be displayed.")
511 CMD_ARGS(
512 { "<fulljid>", "If in the console or a chat window, the full JID for which you wish to see software information." },
513 { "<nick>", "If in a chat room, nickname for which you wish to see software information." })
514 CMD_EXAMPLES(
515 "/software odin@valhalla.edda/laptop",
516 "/software odin@valhalla.edda/phone",
517 "/software thor")
518 },
519
520 { "/status",
521 parse_args, 2, 3, NULL,
522 CMD_SUBFUNCS(
523 { "get", cmd_status_get },
524 { "set", cmd_status_set })
525 CMD_NOMAINFUNC
526 CMD_TAGS(
527 CMD_TAG_CHAT,
528 CMD_TAG_GROUPCHAT)
529 CMD_SYN(
530 "/status set <state> [\"<message>\"]",
531 "/status get <contact>|<nick>")
532 CMD_DESC(
533 "/status get: Find out a contact, or room members presence information. "
534 "/status set: set own status.")
535 CMD_ARGS(
536 { "<state>", "Own status. Possible values: chat, online, away, dnd, xa" },
537 { "<message>", "Optional message to use with the status. Needs quotation marks if it's more than one word." },
538 { "<contact>", "The contact who's presence you which to see." },
539 { "<nick>", "If in a chat room, the occupant who's presence you wish to see." })
540 CMD_EXAMPLES(
541 "/status get odin@valhalla.edda",
542 "/status get jon",
543 "/status set online")
544 },
545
546 { "/resource",
547 parse_args, 1, 2, &cons_resource_setting,
548 CMD_NOSUBFUNCS
549 CMD_MAINFUNC(cmd_resource)
550 CMD_TAGS(
551 CMD_TAG_CHAT,
552 CMD_TAG_UI)
553 CMD_SYN(
554 "/resource set <resource>",
555 "/resource off",
556 "/resource title on|off",
557 "/resource message on|off")
558 CMD_DESC(
559 "Override chat session resource, and manage resource display settings.")
560 CMD_ARGS(
561 { "set <resource>", "Set the resource to which messages will be sent." },
562 { "off", "Let the server choose which resource to route messages to." },
563 { "title on|off", "Show or hide the current resource in the titlebar." },
564 { "message on|off", "Show or hide the resource when showing an incoming message." })
565 CMD_NOEXAMPLES
566 },
567
568 { "/join",
569 parse_args, 0, 5, NULL,
570 CMD_NOSUBFUNCS
571 CMD_MAINFUNC(cmd_join)
572 CMD_TAGS(
573 CMD_TAG_GROUPCHAT)
574 CMD_SYN(
575 "/join",
576 "/join <room> [nick <nick>] [password <password>]")
577 CMD_DESC(
578 "Join a chat room at the conference server. "
579 "If no room is supplied, a generated name will be used with the format private-chat-[UUID]. "
580 "If the domain part is not included in the room name, the account preference 'muc.service' will be used. "
581 "If no nickname is specified the account preference 'muc.nick' will be used which by default is the localpart of your JID. "
582 "If the room doesn't exist, and the server allows it, a new one will be created. "
583 "If you join to a room often, you might also want to add a bookmark (see `/help bookmark`), which also allows to set a default nickname. "
584 "In this case, you should use `/bookmark join`.")
585 CMD_ARGS(
586 { "<room>", "The chat room to join." },
587 { "nick <nick>", "Nickname to use in the room." },
588 { "password <password>", "Password if the room requires one." })
589 CMD_EXAMPLES(
590 "/join",
591 "/join profanity@rooms.dismail.de",
592 "/join profanity@rooms.dismail.de nick mynick",
593 "/join private@conference.jabber.org nick mynick password mypassword",
594 "/join mychannel")
595 },
596
597 { "/invite",
598 parse_args_with_freetext, 1, 3, NULL,
599 CMD_NOSUBFUNCS
600 CMD_MAINFUNC(cmd_invite)
601 CMD_TAGS(
602 CMD_TAG_GROUPCHAT)
603 CMD_SYN(
604 "/invite send <contact> [<message>]",
605 "/invite list",
606 "/invite decline")
607 CMD_DESC(
608 "Manage room invites. "
609 "Send an invite to a contact for the current chat room. "
610 "List received invites. "
611 "Decline them using /invite decline and accept them using /join.")
612 CMD_ARGS(
613 { "send <contact> [<message>]", "The contact you wish to invite. And an optional message." },
614 { "list", "Show all rooms that you have been invited to, and not accepted or declined." },
615 { "decline <room>", "Decline a chat room invitation." })
616 CMD_EXAMPLES(
617 "/invite send gustavo@pollos.tx",
618 "/invite decline profanity@rooms.dismail.de",
619 "/invite list")
620 },
621
622 { "/room",
623 parse_args, 1, 1, NULL,
624 CMD_NOSUBFUNCS
625 CMD_MAINFUNC(cmd_room)
626 CMD_TAGS(
627 CMD_TAG_GROUPCHAT)
628 CMD_SYN(
629 "/room accept|destroy|config")
630 CMD_DESC(
631 "Chat room configuration.")
632 CMD_ARGS(
633 { "accept", "Accept default room configuration." },
634 { "destroy", "Reject default room configuration, and destroy the room." },
635 { "config", "Edit room configuration." })
636 CMD_NOEXAMPLES
637 },
638
639 { "/kick",
640 parse_args_with_freetext, 1, 2, NULL,
641 CMD_NOSUBFUNCS
642 CMD_MAINFUNC(cmd_kick)
643 CMD_TAGS(
644 CMD_TAG_GROUPCHAT)
645 CMD_SYN(
646 "/kick <nick> [<reason>]")
647 CMD_DESC(
648 "Kick occupant from chat room.")
649 CMD_ARGS(
650 { "<nick>", "Nickname of the occupant to kick from the room." },
651 { "<reason>", "Optional reason for kicking the occupant." })
652 CMD_NOEXAMPLES },
653
654 { "/ban",
655 parse_args_with_freetext, 1, 2, NULL,
656 CMD_NOSUBFUNCS
657 CMD_MAINFUNC(cmd_ban)
658 CMD_TAGS(
659 CMD_TAG_GROUPCHAT)
660 CMD_SYN(
661 "/ban <jid> [<reason>]")
662 CMD_DESC(
663 "Ban user from chat room.")
664 CMD_ARGS(
665 { "<jid>", "Bare JID of the user to ban from the room." },
666 { "<reason>", "Optional reason for banning the user." })
667 CMD_NOEXAMPLES
668 },
669
670 { "/subject",
671 parse_args_with_freetext, 0, 2, NULL,
672 CMD_NOSUBFUNCS
673 CMD_MAINFUNC(cmd_subject)
674 CMD_TAGS(
675 CMD_TAG_GROUPCHAT)
676 CMD_SYN(
677 "/subject set <subject>",
678 "/subject edit <subject>",
679 "/subject prepend <text>",
680 "/subject append <text>",
681 "/subject clear")
682 CMD_DESC(
683 "Set, modify, or clear room subject.")
684 CMD_ARGS(
685 { "set <subject>", "Set the room subject." },
686 { "edit <subject>", "Edit the current room subject, tab autocompletion will display the subject to edit." },
687 { "prepend <text>", "Prepend text to the current room subject, use double quotes if a trailing space is needed." },
688 { "append <text>", "Append text to the current room subject, use double quotes if a preceding space is needed." },
689 { "clear", "Clear the room subject." })
690 CMD_NOEXAMPLES
691 },
692
693 { "/affiliation",
694 parse_args_with_freetext, 1, 4, NULL,
695 CMD_NOSUBFUNCS
696 CMD_MAINFUNC(cmd_affiliation)
697 CMD_TAGS(
698 CMD_TAG_GROUPCHAT)
699 CMD_SYN(
700 "/affiliation set <affiliation> <jid> [<reason>]",
701 "/affiliation list [<affiliation>]",
702 "/affiliation request",
703 "/affiliation register")
704 CMD_DESC(
705 "Manage room affiliations. "
706 "Affiliation may be one of owner, admin, member, outcast or none.")
707 CMD_ARGS(
708 { "set <affiliation> <jid> [<reason>]", "Set the affiliation of user with jid, with an optional reason." },
709 { "list [<affiliation>]", "List all users with the specified affiliation, or all if none specified." },
710 { "request", "Request voice."},
711 { "register", "Register your nickname with the MUC."})
712 CMD_NOEXAMPLES
713 },
714
715 { "/role",
716 parse_args_with_freetext, 1, 4, NULL,
717 CMD_NOSUBFUNCS
718 CMD_MAINFUNC(cmd_role)
719 CMD_TAGS(
720 CMD_TAG_GROUPCHAT)
721 CMD_SYN(
722 "/role set <role> <nick> [<reason>]",
723 "/role list [<role>]")
724 CMD_DESC(
725 "Manage room roles. "
726 "Role may be one of moderator, participant, visitor or none.")
727 CMD_ARGS(
728 { "set <role> <nick> [<reason>]", "Set the role of occupant with nick, with an optional reason." },
729 { "list [<role>]", "List all occupants with the specified role, or all if none specified." })
730 CMD_NOEXAMPLES
731 },
732
733 { "/occupants",
734 parse_args, 1, 3, cons_occupants_setting,
735 CMD_NOSUBFUNCS
736 CMD_MAINFUNC(cmd_occupants)
737 CMD_TAGS(
738 CMD_TAG_GROUPCHAT,
739 CMD_TAG_UI)
740 CMD_SYN(
741 "/occupants show|hide [jid|offline]",
742 "/occupants char <char>|none",
743 "/occupants color on|off",
744 "/occupants default show|hide [jid|offline]",
745 "/occupants size [<percent>]",
746 "/occupants indent <indent>",
747 "/occupants header char <char>|none",
748 "/occupants wrap on|off")
749 CMD_DESC(
750 "Show or hide room occupants, and occupants panel display settings.")
751 CMD_ARGS(
752 { "show", "Show the occupants panel in current room." },
753 { "char <char>", "Prefix occupants with specified character." },
754 { "char none", "Remove occupants character prefix." },
755 { "color on", "Enable generated color names (XEP-0392) for occupants" },
756 { "color off", "Disable generated color names (XEP-0392) for occupants" },
757 { "hide", "Hide the occupants panel in current room." },
758 { "show jid", "Show jid in the occupants panel in current room." },
759 { "hide jid", "Hide jid in the occupants panel in current room." },
760 { "show offline", "Show offline occupants panel in current room." },
761 { "hide offline", "Hide offline occupants panel in current room." },
762 { "default show|hide", "Whether occupants are shown by default in new rooms." },
763 { "default show|hide jid", "Whether occupants jids are shown by default in new rooms." },
764 { "default show|hide offline", "Whether offline occupants are shown by default in new rooms." },
765 { "size <percent>", "Percentage of the screen taken by the occupants list in rooms (1-99)." },
766 { "indent <indent>", "Indent contact line by <indent> spaces (0 to 10)." },
767 { "header char <char>", "Prefix occupants headers with specified character." },
768 { "header char none", "Remove occupants header character prefix." },
769 { "wrap on|off", "Enable or disable line wrapping in occupants panel." })
770 CMD_NOEXAMPLES
771 },
772
773 { "/form",
774 parse_args, 1, 2, NULL,
775 CMD_NOSUBFUNCS
776 CMD_MAINFUNC(cmd_form)
777 CMD_TAGS(
778 CMD_TAG_GROUPCHAT)
779 CMD_SYN(
780 "/form show",
781 "/form submit",
782 "/form cancel",
783 "/form help [<tag>]")
784 CMD_DESC(
785 "Form configuration.")
786 CMD_ARGS(
787 { "show", "Show the current form." },
788 { "submit", "Submit the current form." },
789 { "cancel", "Cancel changes to the current form." },
790 { "help [<tag>]", "Display help for form, or a specific field." })
791 CMD_NOEXAMPLES
792 },
793
794 { "/rooms",
795 parse_args, 0, 4, NULL,
796 CMD_NOSUBFUNCS
797 CMD_MAINFUNC(cmd_rooms)
798 CMD_TAGS(
799 CMD_TAG_GROUPCHAT)
800 CMD_SYN(
801 "/rooms",
802 "/rooms filter <text>",
803 "/rooms service <service>",
804 "/rooms service <service> filter <text>",
805 "/rooms cache on|off|clear")
806 CMD_DESC(
807 "List the chat rooms available at the specified conference service. "
808 "If no argument is supplied, the account preference 'muc.service' is used, 'conference.<domain-part>' by default. "
809 "The filter argument only shows rooms that contain the provided text, case insensitive.")
810 CMD_ARGS(
811 { "service <service>", "The conference service to query." },
812 { "filter <text>", "The text to filter results by." },
813 { "cache on|off", "Enable or disable caching of rooms list response, enabled by default." },
814 { "cache clear", "Clear the rooms response cache if enabled." })
815 CMD_EXAMPLES(
816 "/rooms",
817 "/rooms filter development",
818 "/rooms service conference.jabber.org",
819 "/rooms service conference.jabber.org filter \"News Room\"")
820 },
821
822 { "/bookmark",
823 parse_args, 0, 8, NULL,
824 CMD_SUBFUNCS(
825 { "ignore", cmd_bookmark_ignore })
826 CMD_MAINFUNC(cmd_bookmark)
827 CMD_TAGS(
828 CMD_TAG_GROUPCHAT)
829 CMD_SYN(
830 "/bookmark",
831 "/bookmark list [<jid>]",
832 "/bookmark add [<room>] [nick <nick>] [password <password>] [name <roomname>] [autojoin on|off]",
833 "/bookmark update <room> [nick <nick>] [password <password>] [name <roomname>] [autojoin on|off]",
834 "/bookmark remove [<room>]",
835 "/bookmark join <room>",
836 "/bookmark invites on|off",
837 "/bookmark ignore",
838 "/bookmark ignore add <jid>",
839 "/bookmark ignore remove <jid>")
840 CMD_DESC(
841 "Manage bookmarks and join bookmarked rooms. "
842 "If you are in a chat room and no arguments are supplied to `/bookmark add`, autojoin is set to \"on\". "
843 "There is also an autojoin ignore list in case you want to autojoin in many clients but not on Profanity. ")
844 CMD_ARGS(
845 { "list [<jid>]", "List all bookmarks. Or the details of one." },
846 { "add [<room>]", "Add a bookmark, passing no room will bookmark the current room, setting autojoin to \"on\"." },
847 { "remove [<room>]", "Remove a bookmark, passing no room will remove the bookmark for the current room, if one exists." },
848 { "update <room>", "Update the properties associated with a bookmark." },
849 { "nick <nick>", "Nickname used when joining the chat room." },
850 { "password <password>", "Password if required, may be stored in plaintext on your server." },
851 { "name <roomname>", "Optional name for the bookmark. By default localpart of the JID will be used." },
852 { "autojoin on|off", "Whether to join the room automatically on login." },
853 { "join <room>", "Join room using the properties associated with the bookmark." },
854 { "invites on|off", "Whether or not to bookmark accepted room invites, defaults to 'on'." },
855 { "ignore add <barejid>", "Add a bookmark to the autojoin ignore list." },
856 { "ignore remove <barejid>", "Remove a bookmark from the autojoin ignore list." })
857 CMD_EXAMPLES(
858 "/bookmark add room@example.com nick YOURNICK",
859 "/bookmark join room@example.com",
860 "/bookmark update room@example.com nick NEWNICK autojoin on",
861 "/bookmark ignore room@example.com",
862 "/bookmark list",
863 "/bookmark list room@example.com",
864 "/bookmark remove room@example.com")
865 },
866
867 { "/disco",
868 parse_args, 1, 2, NULL,
869 CMD_NOSUBFUNCS
870 CMD_MAINFUNC(cmd_disco)
871 CMD_TAGS(
872 CMD_TAG_DISCOVERY)
873 CMD_SYN(
874 "/disco info [<jid>]",
875 "/disco items [<jid>]")
876 CMD_DESC(
877 "Find out information about an entities supported services. "
878 "Calling with no arguments will query the server you are currently connected to. "
879 "This includes discovering contact addresses for XMPP services (XEP-0157).")
880 CMD_ARGS(
881 { "info [<jid>]", "List protocols and features supported by an entity." },
882 { "items [<jid>]", "List items associated with an entity." })
883 CMD_EXAMPLES(
884 "/disco info",
885 "/disco items myserver.org",
886 "/disco items conference.jabber.org",
887 "/disco info odin@valhalla.edda/laptop")
888 },
889
890 { "/sendfile",
891 parse_args_with_freetext, 1, 1, NULL,
892 CMD_NOSUBFUNCS
893 CMD_MAINFUNC(cmd_sendfile)
894 CMD_TAGS(
895 CMD_TAG_CHAT,
896 CMD_TAG_GROUPCHAT)
897 CMD_SYN(
898 "/sendfile <file>")
899 CMD_DESC(
900 "Send a file using XEP-0363 HTTP file transfer.")
901 CMD_ARGS(
902 { "<file>", "Path to the file." })
903 CMD_EXAMPLES(
904 "/sendfile /etc/hosts",
905 "/sendfile ~/images/sweet_cat.jpg")
906 },
907
908 { "/lastactivity",
909 parse_args, 1, 2, NULL,
910 CMD_NOSUBFUNCS
911 CMD_MAINFUNC(cmd_lastactivity)
912 CMD_TAGS(
913 CMD_TAG_PRESENCE)
914 CMD_SYN(
915 "/lastactivity set on|off",
916 "/lastactivity get [<jid>]")
917 CMD_DESC(
918 "Enable/disable sending last activity, and send last activity requests.")
919 CMD_ARGS(
920 { "on|off", "Enable or disable sending of last activity." },
921 { "<jid>", "The JID of the entity to query. Omitting the JID will query your server for its uptime." })
922 CMD_EXAMPLES(
923 "/lastactivity get",
924 "/lastactivity set off",
925 "/lastactivity get freyja@asgaard.edda",
926 "/lastactivity get freyja@asgaard.edda/laptop",
927 "/lastactivity get someserver.com")
928 },
929
930 { "/nick",
931 parse_args_with_freetext, 1, 1, NULL,
932 CMD_NOSUBFUNCS
933 CMD_MAINFUNC(cmd_nick)
934 CMD_TAGS(
935 CMD_TAG_GROUPCHAT)
936 CMD_SYN(
937 "/nick <nickname>")
938 CMD_DESC(
939 "Change your nickname in the current chat room.")
940 CMD_ARGS(
941 { "<nickname>", "Your new nickname." })
942 CMD_NOEXAMPLES
943 },
944
945 { "/win",
946 parse_args, 1, 1, NULL,
947 CMD_NOSUBFUNCS
948 CMD_MAINFUNC(cmd_win)
949 CMD_TAGS(
950 CMD_TAG_UI)
951 CMD_SYN(
952 "/win console",
953 "/win <num>",
954 "/win <barejid>",
955 "/win <nick>",
956 "/win <roomjid>",
957 "/win <roomoccupantjid>",
958 "/win xmlconsole",
959 "/win <plugin>")
960 CMD_DESC(
961 "Move to the specified window.")
962 CMD_ARGS(
963 { "console", "Focus the Console window." },
964 { "<num>", "Focus specified window number." },
965 { "<barejid>", "Focus chat window with contact by JID if open." },
966 { "<nick>", "Focus chat window with contact by nickname if open." },
967 { "<roomjid>", "Focus chat room window with roomjid if open." },
968 { "<roomoccupantjid>", "Focus private chat roomoccupantjid if open." },
969 { "xmlconsole", "Focus the XML Console window if open." },
970 { "<plugin>", "Focus the plugin window." })
971 CMD_EXAMPLES(
972 "/win console",
973 "/win 4",
974 "/win odin@valhalla.edda",
975 "/win Eddie",
976 "/win bigroom@conference.chat.org",
977 "/win bigroom@conference.chat.org/thor",
978 "/win wikipedia")
979 },
980
981 { "/wins",
982 parse_args, 0, 3, NULL,
983 CMD_SUBFUNCS(
984 { "unread", cmd_wins_unread },
985 { "attention", cmd_wins_attention },
986 { "prune", cmd_wins_prune },
987 { "swap", cmd_wins_swap })
988 CMD_MAINFUNC(cmd_wins)
989 CMD_TAGS(
990 CMD_TAG_UI)
991 CMD_SYN(
992 "/wins",
993 "/wins unread",
994 "/wins attention",
995 "/wins prune",
996 "/wins swap <source> <target>")
997 CMD_DESC(
998 "Manage windows. "
999 "Passing no argument will list all currently active windows and information about their usage.")
1000 CMD_ARGS(
1001 { "unread", "List windows with unread messages." },
1002 { "attention", "List windows that have been marked with the attention flag (alt+v). You can toggle between marked windows with alt+m." },
1003 { "prune", "Close all windows with no unread messages." },
1004 { "swap <source> <target>", "Swap windows, target may be an empty position." })
1005 CMD_NOEXAMPLES
1006 },
1007
1008 { "/sub",
1009 parse_args, 1, 2, NULL,
1010 CMD_NOSUBFUNCS
1011 CMD_MAINFUNC(cmd_sub)
1012 CMD_TAGS(
1013 CMD_TAG_ROSTER)
1014 CMD_SYN(
1015 "/sub request [<jid>]",
1016 "/sub allow [<jid>]",
1017 "/sub deny [<jid>]",
1018 "/sub show [<jid>]",
1019 "/sub sent",
1020 "/sub received")
1021 CMD_DESC(
1022 "Manage subscriptions to contact presence. "
1023 "If jid is omitted, the contact of the current window is used.")
1024 CMD_ARGS(
1025 { "request [<jid>]", "Send a subscription request to the user." },
1026 { "allow [<jid>]", "Approve a contact's subscription request." },
1027 { "deny [<jid>]", "Remove subscription for a contact, or deny a request." },
1028 { "show [<jid>]", "Show subscription status for a contact." },
1029 { "sent", "Show all sent subscription requests pending a response." },
1030 { "received", "Show all received subscription requests awaiting your response." })
1031 CMD_EXAMPLES(
1032 "/sub request odin@valhalla.edda",
1033 "/sub allow odin@valhalla.edda",
1034 "/sub request",
1035 "/sub sent")
1036 },
1037
1038 { "/who",
1039 parse_args, 0, 2, NULL,
1040 CMD_NOSUBFUNCS
1041 CMD_MAINFUNC(cmd_who)
1042 CMD_TAGS(
1043 CMD_TAG_CHAT,
1044 CMD_TAG_GROUPCHAT,
1045 CMD_TAG_ROSTER)
1046 CMD_SYN(
1047 "/who",
1048 "/who online|offline|away|dnd|xa|chat|available|unavailable|any [<group>]",
1049 "/who moderator|participant|visitor",
1050 "/who owner|admin|member")
1051 CMD_DESC(
1052 "Show contacts or room occupants with chosen status, role or affiliation.")
1053 CMD_ARGS(
1054 { "offline|away|dnd|xa|chat", "Show contacts or room occupants with specified presence." },
1055 { "online", "Contacts that are online, chat, away, xa, dnd." },
1056 { "available", "Contacts that are available for chat - online, chat." },
1057 { "unavailable", "Contacts that are not available for chat - offline, away, xa, dnd." },
1058 { "any", "Contacts with any status (same as calling with no argument)." },
1059 { "<group>", "Filter the results by the specified roster group, not applicable in chat rooms." },
1060 { "moderator|participant|visitor", "Room occupants with the specified role." },
1061 { "owner|admin|member", "Room occupants with the specified affiliation." })
1062 CMD_EXAMPLES(
1063 "/who",
1064 "/who xa",
1065 "/who online friends",
1066 "/who any family",
1067 "/who participant",
1068 "/who admin")
1069 },
1070
1071 { "/close",
1072 parse_args, 0, 1, NULL,
1073 CMD_NOSUBFUNCS
1074 CMD_MAINFUNC(cmd_close)
1075 CMD_TAGS(
1076 CMD_TAG_UI)
1077 CMD_SYN(
1078 "/close",
1079 "/close <num>",
1080 "/close <barejid>",
1081 "/close <nick>",
1082 "/close <roomjid>",
1083 "/close <roomoccupantjid>",
1084 "/close xmlconsole",
1085 "/close all|read")
1086 CMD_DESC(
1087 "Close windows. "
1088 "Passing no argument closes the current window.")
1089 CMD_ARGS(
1090 { "<num>", "Close specified window number." },
1091 { "<barejid>", "Close chat window with contact by JID if open." },
1092 { "<nick>", "Close chat window with contact by nickname if open." },
1093 { "<roomjid>", "Close chat room window with roomjid if open." },
1094 { "<roomoccupantjid>", "Close private chat roomoccupantjid if open." },
1095 { "xmlconsole", "Close the XML Console window if open." },
1096 { "all", "Close all windows." },
1097 { "read", "Close all windows that have no unread messages." })
1098 CMD_NOEXAMPLES
1099 },
1100
1101 { "/clear",
1102 parse_args, 0, 2, NULL,
1103 CMD_NOSUBFUNCS
1104 CMD_MAINFUNC(cmd_clear)
1105 CMD_TAGS(
1106 CMD_TAG_UI)
1107 CMD_SYN(
1108 "/clear",
1109 "/clear persist_history <on|off>")
1110 CMD_DESC(
1111 "Clear the current window. "
1112 "If you set persist_history you can still access the history by pressing PAGE UP.")
1113 CMD_ARGS(
1114 { "persist_history on|off", "Whether or not to clear the screen persistently." })
1115 CMD_EXAMPLES(
1116 "/clear",
1117 "/clear persist_history",
1118 "/clear persist_history on")
1119 },
1120
1121 { "/quit",
1122 parse_args, 0, 0, NULL,
1123 CMD_NOSUBFUNCS
1124 CMD_MAINFUNC(cmd_quit)
1125 CMD_NOTAGS
1126 CMD_SYN(
1127 "/quit")
1128 CMD_DESC(
1129 "Logout of any current session, and quit Profanity.")
1130 CMD_NOARGS
1131 CMD_NOEXAMPLES
1132 },
1133
1134 { "/privileges",
1135 parse_args, 1, 1, &cons_privileges_setting,
1136 CMD_NOSUBFUNCS
1137 CMD_MAINFUNC(cmd_privileges)
1138 CMD_TAGS(
1139 CMD_TAG_GROUPCHAT,
1140 CMD_TAG_UI)
1141 CMD_SYN(
1142 "/privileges on|off")
1143 CMD_DESC(
1144 "Group occupants panel by role, and show role information in chat rooms.")
1145 CMD_ARGS(
1146 { "on|off", "Enable or disable privilege information." })
1147 CMD_NOEXAMPLES
1148 },
1149
1150 { "/charset",
1151 parse_args, 0, 0, NULL,
1152 CMD_NOSUBFUNCS
1153 CMD_MAINFUNC(cmd_charset)
1154 CMD_TAGS(
1155 CMD_TAG_UI)
1156 CMD_SYN(
1157 "/charset")
1158 CMD_DESC(
1159 "Display information about the current character set supported by the terminal. ")
1160 CMD_NOARGS
1161 CMD_NOEXAMPLES
1162 },
1163
1164 { "/beep",
1165 parse_args, 1, 1, &cons_beep_setting,
1166 CMD_NOSUBFUNCS
1167 CMD_MAINFUNC(cmd_beep)
1168 CMD_TAGS(
1169 CMD_TAG_UI)
1170 CMD_SYN(
1171 "/beep on|off")
1172 CMD_DESC(
1173 "Switch the terminal bell on or off. "
1174 "The bell will sound when incoming messages are received. "
1175 "If the terminal does not support sounds, it may attempt to flash the screen instead.")
1176 CMD_ARGS(
1177 { "on|off", "Enable or disable terminal bell." })
1178 CMD_NOEXAMPLES
1179 },
1180
1181 { "/console",
1182 parse_args, 2, 2, &cons_console_setting,
1183 CMD_NOSUBFUNCS
1184 CMD_MAINFUNC(cmd_console)
1185 CMD_TAGS(
1186 CMD_TAG_UI,
1187 CMD_TAG_CHAT,
1188 CMD_TAG_GROUPCHAT)
1189 CMD_SYN(
1190 "/console chat all|first|none",
1191 "/console muc all|first|mention|none",
1192 "/console private all|first|none")
1193 CMD_DESC(
1194 "Configure what is displayed in the console window when messages are received. "
1195 "The default is set to 'all' for all types of messages.")
1196 CMD_ARGS(
1197 { "chat all", "Indicate all new chat messages in the console." },
1198 { "chat first", "Indicate only the first new message per chat in the console." },
1199 { "chat none", "Do not show any new chat messages in the console window." },
1200 { "muc all", "Indicate all new chat room messages in the console." },
1201 { "muc first", "Indicate only the first new message in each room in the console." },
1202 { "muc mention", "Indicate only messages in which you have beeen mentioned in the console." },
1203 { "muc none", "Do not show any new chat room messages in the console window." },
1204 { "private all", "Indicate all new private room messages in the console." },
1205 { "private first", "Indicate only the first private room message in the console." },
1206 { "private none", "Do not show any new private room messages in the console window." })
1207 CMD_NOEXAMPLES
1208 },
1209
1210 { "/presence",
1211 parse_args, 2, 2, &cons_presence_setting,
1212 CMD_NOSUBFUNCS
1213 CMD_MAINFUNC(cmd_presence)
1214 CMD_TAGS(
1215 CMD_TAG_UI,
1216 CMD_TAG_CHAT,
1217 CMD_TAG_GROUPCHAT)
1218 CMD_SYN(
1219 "/presence titlebar on|off",
1220 "/presence console all|online|none",
1221 "/presence chat all|online|none",
1222 "/presence room all|online|none")
1223 CMD_DESC(
1224 "Show the contacts presence in the titlebar and configure presence messages in different window types.")
1225 CMD_ARGS(
1226 { "titlebar on|off", "Switch display of the contacts presence in the titlebar on or off." },
1227 { "console all", "Show all presence changes in the console window." },
1228 { "console online", "Show only online/offline presence changes in the console window." },
1229 { "console none", "Don't show any presence changes in the console window." },
1230 { "chat all", "Show all presence changes in the chat windows." },
1231 { "chat online", "Show only online/offline presence changes in chat windows." },
1232 { "chat none", "Don't show any presence changes in chat windows." },
1233 { "room all", "Show all presence changes in chat room windows." },
1234 { "room online", "Show only online/offline presence changes in chat room windows." },
1235 { "room none", "Don't show any presence changes in chat room windows." })
1236 CMD_EXAMPLES(
1237 "/presence titlebar off",
1238 "/presence console none",
1239 "/presence chat online",
1240 "/presence room all")
1241 },
1242
1243 { "/wrap",
1244 parse_args, 1, 1, &cons_wrap_setting,
1245 CMD_NOSUBFUNCS
1246 CMD_MAINFUNC(cmd_wrap)
1247 CMD_TAGS(
1248 CMD_TAG_UI)
1249 CMD_SYN(
1250 "/wrap on|off")
1251 CMD_DESC(
1252 "Word wrapping.")
1253 CMD_ARGS(
1254 { "on|off", "Enable or disable word wrapping in the main window." })
1255 CMD_NOEXAMPLES
1256 },
1257
1258 { "/time",
1259 parse_args, 1, 3, &cons_time_setting,
1260 CMD_NOSUBFUNCS
1261 CMD_MAINFUNC(cmd_time)
1262 CMD_TAGS(
1263 CMD_TAG_UI)
1264 CMD_SYN(
1265 "/time all|console|chat|muc|config|private|xml set <format>",
1266 "/time all|console|chat|muc|config|private|xml off",
1267 "/time statusbar set <format>",
1268 "/time statusbar off",
1269 "/time lastactivity set <format>")
1270 CMD_DESC(
1271 "Configure time display preferences. "
1272 "Time formats are strings supported by g_date_time_format. "
1273 "See https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-format for more details. "
1274 "Setting the format to an unsupported string, will display the string. "
1275 "If the format contains spaces, it must be surrounded with double quotes.")
1276 CMD_ARGS(
1277 { "console set <format>", "Set time format for console window." },
1278 { "console off", "Do not show time in console window." },
1279 { "chat set <format>", "Set time format for chat windows." },
1280 { "chat off", "Do not show time in chat windows." },
1281 { "muc set <format>", "Set time format for chat room windows." },
1282 { "muc off", "Do not show time in chat room windows." },
1283 { "config set <format>", "Set time format for config windows." },
1284 { "config off", "Do not show time in config windows." },
1285 { "private set <format>", "Set time format for private chat windows." },
1286 { "private off", "Do not show time in private chat windows." },
1287 { "xml set <format>", "Set time format for XML console window." },
1288 { "xml off", "Do not show time in XML console window." },
1289 { "statusbar set <format>", "Change time format in statusbar." },
1290 { "statusbar off", "Do not show time in status bar." },
1291 { "lastactivity set <format>", "Change time format for last activity." },
1292 { "all set <format>", "Set time for: console, chat, muc, config, private and xml windows." },
1293 { "all off", "Do not show time for: console, chat, muc, config, private and xml windows." })
1294 CMD_EXAMPLES(
1295 "/time console set %H:%M:%S",
1296 "/time chat set \"%d-%m-%y %H:%M:%S\"",
1297 "/time xml off",
1298 "/time statusbar set %H:%M",
1299 "/time lastactivity set \"%d-%m-%y %H:%M:%S\"",
1300 "/time all set \"%d-%m-%y %H:%M:%S\"")
1301 },
1302
1303 { "/inpblock",
1304 parse_args, 2, 2, &cons_inpblock_setting,
1305 CMD_NOSUBFUNCS
1306 CMD_MAINFUNC(cmd_inpblock)
1307 CMD_TAGS(
1308 CMD_TAG_UI)
1309 CMD_SYN(
1310 "/inpblock timeout <millis>",
1311 "/inpblock dynamic on|off")
1312 CMD_DESC(
1313 "How long to wait for keyboard input before checking for new messages or checking for state changes such as 'idle'.")
1314 CMD_ARGS(
1315 { "timeout <millis>", "Time to wait (1-1000) in milliseconds before reading input from the terminal buffer, default: 1000." },
1316 { "dynamic on|off", "Start with 0 millis and dynamically increase up to timeout when no activity, default: on." })
1317 CMD_NOEXAMPLES },
1318
1319
1320 { "/titlebar",
1321 parse_args, 1, 2, &cons_titlebar_setting,
1322 CMD_SUBFUNCS(
1323 { "show", cmd_titlebar_show_hide },
1324 { "hide", cmd_titlebar_show_hide })
1325 CMD_MAINFUNC(cmd_titlebar)
1326 CMD_TAGS(
1327 CMD_TAG_UI)
1328 CMD_SYN(
1329 "/titlebar up",
1330 "/titlebar down",
1331 "/titlebar show|hide [encwarn|resource|tls]")
1332 CMD_DESC(
1333 "Titlebar settings.")
1334 CMD_ARGS(
1335 { "up", "Move the title bar up the screen." },
1336 { "down", "Move the title bar down the screen." },
1337 { "show tls", "Show or hide TLS indicator in the titlebar." },
1338 { "show encwarn", "Enable or disable the unencrypted warning message in the titlebar." },
1339 { "show resource", "Show or hide the current resource in the titlebar." },
1340 { "show name", "In case of a MUC. Show the MUC name in the titlebar." },
1341 { "show jid", "In case of a MUC. Show the JID in the titlebar." })
1342 CMD_EXAMPLES(
1343 "/titlebar up",
1344 "/titlebar show tls",
1345 "/titlebar hide encwarn")
1346 },
1347
1348 { "/mainwin",
1349 parse_args, 1, 1, &cons_winpos_setting,
1350 CMD_NOSUBFUNCS
1351 CMD_MAINFUNC(cmd_mainwin)
1352 CMD_TAGS(
1353 CMD_TAG_UI)
1354 CMD_SYN(
1355 "/mainwin up",
1356 "/mainwin down")
1357 CMD_DESC(
1358 "Move the main window.")
1359 CMD_ARGS(
1360 { "up", "Move the main window up the screen." },
1361 { "down", "Move the main window down the screen." })
1362 CMD_NOEXAMPLES
1363 },
1364
1365 { "/statusbar",
1366 parse_args, 1, 2, &cons_statusbar_setting,
1367 CMD_NOSUBFUNCS
1368 CMD_MAINFUNC(cmd_statusbar)
1369 CMD_TAGS(
1370 CMD_TAG_UI)
1371 CMD_SYN(
1372 "/statusbar show name|number|read",
1373 "/statusbar hide name|number|read",
1374 "/statusbar maxtabs <value>",
1375 "/statusbar tablen <value>",
1376 "/statusbar self user|barejid|fulljid|off",
1377 "/statusbar chat user|jid",
1378 "/statusbar room room|jid",
1379 "/statusbar up",
1380 "/statusbar down")
1381 CMD_DESC(
1382 "Manage statusbar display preferences.")
1383 CMD_ARGS(
1384 { "maxtabs <value>", "Set the maximum number of tabs to display, <value> must be between 0 and 10." },
1385 { "tablen <value>", "Set the maximum number of characters to show as the tab name, 0 sets to unlimited." },
1386 { "show|hide name", "Show or hide names in tabs." },
1387 { "show|hide number", "Show or hide numbers in tabs." },
1388 { "show|hide read", "Show or hide inactive tabs." },
1389 { "self user|barejid|fulljid", "Show account user name, barejid, fulljid as status bar title." },
1390 { "self off", "Disable showing self as status bar title." },
1391 { "chat user|jid", "Show users name, or the fulljid if no nick is present for chat tabs." },
1392 { "room room|jid", "Show room name, or the fulljid for room tabs." },
1393 { "up", "Move the status bar up the screen." },
1394 { "down", "Move the status bar down the screen." })
1395 CMD_EXAMPLES(
1396 "/statusbar maxtabs 8",
1397 "/statusbar tablen 5",
1398 "/statusbar self user",
1399 "/statusbar chat jid",
1400 "/statusbar hide read",
1401 "/statusbar hide name")
1402 },
1403
1404 { "/inputwin",
1405 parse_args, 1, 1, &cons_winpos_setting,
1406 CMD_NOSUBFUNCS
1407 CMD_MAINFUNC(cmd_inputwin)
1408 CMD_TAGS(
1409 CMD_TAG_UI)
1410 CMD_SYN(
1411 "/inputwin up",
1412 "/inputwin down")
1413 CMD_DESC(
1414 "Move the input window.")
1415 CMD_ARGS(
1416 { "up", "Move the input window up the screen." },
1417 { "down", "Move the input window down the screen." })
1418 CMD_NOEXAMPLES
1419 },
1420
1421 { "/notify",
1422 parse_args_with_freetext, 0, 4, NULL,
1423 CMD_NOSUBFUNCS
1424 CMD_MAINFUNC(cmd_notify)
1425 CMD_TAGS(
1426 CMD_TAG_UI,
1427 CMD_TAG_CHAT,
1428 CMD_TAG_GROUPCHAT)
1429 CMD_SYN(
1430 "/notify chat on|off",
1431 "/notify chat current on|off",
1432 "/notify chat text on|off",
1433 "/notify room on|off",
1434 "/notify room mention on|off",
1435 "/notify room mention case_sensitive|case_insensitive",
1436 "/notify room mention word_whole|word_part",
1437 "/notify room current on|off",
1438 "/notify room text on|off",
1439 "/notify room trigger add <text>",
1440 "/notify room trigger remove <text>",
1441 "/notify room trigger list",
1442 "/notify room trigger on|off",
1443 "/notify on|off",
1444 "/notify mention on|off",
1445 "/notify trigger on|off",
1446 "/notify reset",
1447 "/notify remind <seconds>",
1448 "/notify typing on|off",
1449 "/notify typing current on|off",
1450 "/notify invite on|off",
1451 "/notify sub on|off")
1452 CMD_DESC(
1453 "Configure desktop notifications. "
1454 "To configure presence update messages in the console, chat and chat room windows, see '/help presence'.")
1455 CMD_ARGS(
1456 { "chat on|off", "Notifications for regular chat messages." },
1457 { "chat current on|off", "Whether to show regular chat message notifications when the window is focused." },
1458 { "chat text on|off", "Show message text in regular message notifications." },
1459 { "room on|off", "Notifications for all chat room messages." },
1460 { "room mention on|off", "Notifications for chat room messages when your nick is mentioned." },
1461 { "room mention case_sensitive", "Set room mention notifications as case sensitive." },
1462 { "room mention case_insensitive", "Set room mention notifications as case insensitive." },
1463 { "room mention word_whole", "Set room mention notifications only on whole word match, i.e. when nickname is not part of a larger word." },
1464 { "room mention word_part", "Set room mention notifications on partial word match, i.e. nickname may be part of a larger word." },
1465 { "room current on|off", "Whether to show all chat room messages notifications when the window is focused." },
1466 { "room text on|off", "Show message text in chat room message notifications." },
1467 { "room trigger add <text>", "Notify when specified text included in all chat room messages." },
1468 { "room trigger remove <text>", "Remove chat room notification trigger." },
1469 { "room trigger list", "List all chat room highlight triggers." },
1470 { "room trigger on|off", "Enable or disable all chat room notification triggers." },
1471 { "on|off", "Override the global message setting for the current chat room." },
1472 { "mention on|off", "Override the global 'mention' setting for the current chat room." },
1473 { "trigger on|off", "Override the global 'trigger' setting for the current chat room." },
1474 { "reset", "Reset to global notification settings for the current chat room." },
1475 { "remind <seconds>", "Notification reminder period for unread messages, use 0 to disable." },
1476 { "typing on|off", "Notifications when contacts are typing." },
1477 { "typing current on|off", "Whether typing notifications are triggered for the current window." },
1478 { "invite on|off", "Notifications for chat room invites." },
1479 { "sub on|off", "Notifications for subscription requests." })
1480 CMD_EXAMPLES(
1481 "/notify chat on",
1482 "/notify chat text on",
1483 "/notify room mention on",
1484 "/notify room trigger add beer",
1485 "/notify room trigger on",
1486 "/notify room current off",
1487 "/notify room text off",
1488 "/notify remind 60",
1489 "/notify typing on",
1490 "/notify invite on")
1491 },
1492
1493 { "/flash",
1494 parse_args, 1, 1, &cons_flash_setting,
1495 CMD_NOSUBFUNCS
1496 CMD_MAINFUNC(cmd_flash)
1497 CMD_TAGS(
1498 CMD_TAG_UI)
1499 CMD_SYN(
1500 "/flash on|off")
1501 CMD_DESC(
1502 "Make the terminal flash when incoming messages are received in another window. "
1503 "If the terminal doesn't support flashing, it may attempt to beep.")
1504 CMD_ARGS(
1505 { "on|off", "Enable or disable terminal flash." })
1506 CMD_NOEXAMPLES
1507 },
1508
1509 { "/tray",
1510 parse_args, 1, 2, &cons_tray_setting,
1511 CMD_NOSUBFUNCS
1512 CMD_MAINFUNC(cmd_tray)
1513 CMD_TAGS(
1514 CMD_TAG_UI)
1515 CMD_SYN(
1516 "/tray on|off",
1517 "/tray read on|off",
1518 "/tray timer <seconds>")
1519 CMD_DESC(
1520 "Display an icon in the tray that will indicate new messages.")
1521 CMD_ARGS(
1522 { "on|off", "Show tray icon." },
1523 { "read on|off", "Show tray icon when no unread messages." },
1524 { "timer <seconds>", "Set tray icon timer, seconds must be between 1-10." })
1525 CMD_NOEXAMPLES
1526 },
1527
1528 { "/intype",
1529 parse_args, 2, 2, &cons_intype_setting,
1530 CMD_NOSUBFUNCS
1531 CMD_MAINFUNC(cmd_intype)
1532 CMD_TAGS(
1533 CMD_TAG_UI,
1534 CMD_TAG_CHAT)
1535 CMD_SYN(
1536 "/intype console|titlebar on|off")
1537 CMD_DESC(
1538 "Show when a contact is typing in the console, and in active message window.")
1539 CMD_ARGS(
1540 { "titlebar on|off", "Enable or disable contact typing messages notification in titlebar." },
1541 { "console on|off", "Enable or disable contact typing messages notification in console window." })
1542 CMD_NOEXAMPLES
1543 },
1544
1545 { "/splash",
1546 parse_args, 1, 1, &cons_splash_setting,
1547 CMD_NOSUBFUNCS
1548 CMD_MAINFUNC(cmd_splash)
1549 CMD_TAGS(
1550 CMD_TAG_UI)
1551 CMD_SYN(
1552 "/splash on|off")
1553 CMD_DESC(
1554 "Switch on or off the ascii logo on start up and when the /about command is called.")
1555 CMD_ARGS(
1556 { "on|off", "Enable or disable splash logo." })
1557 CMD_NOEXAMPLES
1558 },
1559
1560 { "/autoconnect",
1561 parse_args, 1, 2, &cons_autoconnect_setting,
1562 CMD_NOSUBFUNCS
1563 CMD_MAINFUNC(cmd_autoconnect)
1564 CMD_TAGS(
1565 CMD_TAG_CONNECTION)
1566 CMD_SYN(
1567 "/autoconnect set <account>",
1568 "/autoconnect off")
1569 CMD_DESC(
1570 "Enable or disable autoconnect on start up. "
1571 "The setting can be overridden by the -a (--account) command line option.")
1572 CMD_ARGS(
1573 { "set <account>", "Connect with account on start up." },
1574 { "off", "Disable autoconnect." })
1575 CMD_EXAMPLES(
1576 "/autoconnect set ulfhednar@valhalla.edda",
1577 "/autoconnect off")
1578 },
1579
1580 { "/vercheck",
1581 parse_args, 0, 1, NULL,
1582 CMD_NOSUBFUNCS
1583 CMD_MAINFUNC(cmd_vercheck)
1584 CMD_TAGS(
1585 CMD_TAG_UI)
1586 CMD_SYN(
1587 "/vercheck on|off")
1588 CMD_DESC(
1589 "Check for new versions when Profanity starts, and when the /about command is run.")
1590 CMD_ARGS(
1591 { "on|off", "Enable or disable the version check." })
1592 CMD_NOEXAMPLES
1593 },
1594
1595 { "/wintitle",
1596 parse_args, 2, 2, &cons_wintitle_setting,
1597 CMD_NOSUBFUNCS
1598 CMD_MAINFUNC(cmd_wintitle)
1599 CMD_TAGS(
1600 CMD_TAG_UI)
1601 CMD_SYN(
1602 "/wintitle show on|off",
1603 "/wintitle goodbye on|off")
1604 CMD_DESC(
1605 "Allow Profanity to modify the window title bar.")
1606 CMD_ARGS(
1607 { "show on|off", "Show current logged in user, and unread messages as the window title." },
1608 { "goodbye on|off", "Show a message in the title when exiting profanity." })
1609 CMD_NOEXAMPLES
1610 },
1611
1612 { "/alias",
1613 parse_args_with_freetext, 1, 3, NULL,
1614 CMD_NOSUBFUNCS
1615 CMD_MAINFUNC(cmd_alias)
1616 CMD_NOTAGS
1617 CMD_SYN(
1618 "/alias list",
1619 "/alias add <name> <value>",
1620 "/alias remove <name>")
1621 CMD_DESC(
1622 "Add, remove or list command aliases.")
1623 CMD_ARGS(
1624 { "list", "List all aliases." },
1625 { "add <name> <value>", "Add a new command alias." },
1626 { "remove <name>", "Remove a command alias." })
1627 CMD_EXAMPLES(
1628 "/alias add friends /who online friends",
1629 "/alias add /q /quit",
1630 "/alias add a /away \"I'm in a meeting.\"",
1631 "/alias remove q",
1632 "/alias list")
1633 },
1634
1635 { "/logging",
1636 parse_args, 2, 3, &cons_logging_setting,
1637 CMD_NOSUBFUNCS
1638 CMD_MAINFUNC(cmd_logging)
1639 CMD_TAGS(
1640 CMD_TAG_CHAT)
1641 CMD_SYN(
1642 "/logging chat|group on|off")
1643 CMD_DESC(
1644 "Configure chat logging. "
1645 "Switch logging on or off. "
1646 "Chat logging will be enabled if /history is set to on. "
1647 "When disabling this option, /history will also be disabled. ")
1648 CMD_ARGS(
1649 { "chat on|off", "Enable/Disable regular chat logging." },
1650 { "group on|off", "Enable/Disable groupchat (room) logging." })
1651 CMD_EXAMPLES(
1652 "/logging chat on",
1653 "/logging group off")
1654 },
1655
1656 { "/states",
1657 parse_args, 1, 1, &cons_states_setting,
1658 CMD_NOSUBFUNCS
1659 CMD_MAINFUNC(cmd_states)
1660 CMD_TAGS(
1661 CMD_TAG_CHAT)
1662 CMD_SYN(
1663 "/states on|off")
1664 CMD_DESC(
1665 "Send chat state notifications to recipient during chat sessions, such as typing, paused, active, gone.")
1666 CMD_ARGS(
1667 { "on|off", "Enable or disable sending of chat state notifications." })
1668 CMD_NOEXAMPLES },
1669
1670 { "/pgp",
1671 parse_args, 1, 3, NULL,
1672 CMD_NOSUBFUNCS
1673 CMD_MAINFUNC(cmd_pgp)
1674 CMD_TAGS(
1675 CMD_TAG_CHAT,
1676 CMD_TAG_UI)
1677 CMD_SYN(
1678 "/pgp libver",
1679 "/pgp keys",
1680 "/pgp contacts",
1681 "/pgp setkey <contact> <keyid>",
1682 "/pgp start [<contact>]",
1683 "/pgp end",
1684 "/pgp log on|off|redact",
1685 "/pgp char <char>",
1686 "/pgp sendfile on|off")
1687 CMD_DESC(
1688 "Open PGP commands to manage keys, and perform PGP encryption during chat sessions. "
1689 "See the /account command to set your own PGP key.")
1690 CMD_ARGS(
1691 { "libver", "Show which version of the libgpgme library is being used." },
1692 { "keys", "List all keys known to the system." },
1693 { "contacts", "Show contacts with assigned public keys." },
1694 { "setkey <contact> <keyid>", "Manually associate a contact with a public key." },
1695 { "start [<contact>]", "Start PGP encrypted chat, current contact will be used if not specified." },
1696 { "end", "End PGP encrypted chat with the current recipient." },
1697 { "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." },
1698 { "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." },
1699 { "char <char>", "Set the character to be displayed next to PGP encrypted messages." },
1700 { "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP." })
1701 CMD_EXAMPLES(
1702 "/pgp log off",
1703 "/pgp setkey odin@valhalla.edda BA19CACE5A9592C5",
1704 "/pgp start odin@valhalla.edda",
1705 "/pgp end",
1706 "/pgp char P")
1707 },
1708
1709 // XEP-0373: OpenPGP for XMPP
1710 #ifdef HAVE_LIBGPGME
1711 { "/ox",
1712 parse_args, 1, 3, NULL,
1713 CMD_NOSUBFUNCS
1714 CMD_MAINFUNC(cmd_ox)
1715 CMD_TAGS(
1716 CMD_TAG_CHAT,
1717 CMD_TAG_UI)
1718 CMD_SYN(
1719 "/ox keys",
1720 "/ox contacts",
1721 "/ox start [<contact>]",
1722 "/ox end",
1723 "/ox log on|off|redact",
1724 "/ox char <char>",
1725 "/ox sendfile on|off",
1726 "/ox announce <file>",
1727 "/ox discover <jid>",
1728 "/ox request <jid> <keyid>")
1729 CMD_DESC(
1730 "OpenPGP (OX) commands to manage keys, and perform OpenPGP encryption during chat sessions. "
1731 "Your OpenPGP key needs a user-id with your JID URI (xmpp:local@domain.tld). "
1732 "A key can be generated with \"gpg --quick-gen-key xmpp:local@domain.tld future-default default 3y\".")
1733 CMD_ARGS(
1734 { "keys", "List all keys known to the system." },
1735 { "contacts", "Show contacts with assigned public keys." },
1736 { "start [<contact>]", "Start PGP encrypted chat, current contact will be used if not specified." },
1737 { "end", "End PGP encrypted chat with the current recipient." },
1738 { "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." },
1739 { "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." },
1740 { "char <char>", "Set the character to be displayed next to PGP encrypted messages." },
1741 { "announce <file>", "Announce a public key by pushing it on the XMPP Server" },
1742 { "discover <jid>", "Discover public keys of a jid. The OpenPGP Key IDs will be displayed" },
1743 { "request <jid>", "Request public keys" },
1744 { "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP." })
1745 CMD_EXAMPLES(
1746 "/ox log off",
1747 "/ox start odin@valhalla.edda",
1748 "/ox end",
1749 "/ox char X")
1750 },
1751 #endif // HAVE_LIBGPGME
1752
1753 { "/otr",
1754 parse_args, 1, 3, NULL,
1755 CMD_SUBFUNCS(
1756 { "char", cmd_otr_char },
1757 { "log", cmd_otr_log },
1758 { "libver", cmd_otr_libver },
1759 { "policy", cmd_otr_policy },
1760 { "gen", cmd_otr_gen },
1761 { "myfp", cmd_otr_myfp },
1762 { "theirfp", cmd_otr_theirfp },
1763 { "start", cmd_otr_start },
1764 { "end", cmd_otr_end },
1765 { "trust", cmd_otr_trust },
1766 { "untrust", cmd_otr_untrust },
1767 { "secret", cmd_otr_secret },
1768 { "question", cmd_otr_question },
1769 { "answer", cmd_otr_answer },
1770 { "sendfile", cmd_otr_sendfile })
1771 CMD_NOMAINFUNC
1772 CMD_TAGS(
1773 CMD_TAG_CHAT,
1774 CMD_TAG_UI)
1775 CMD_SYN(
1776 "/otr libver",
1777 "/otr gen",
1778 "/otr myfp|theirfp",
1779 "/otr start [<contact>]",
1780 "/otr end",
1781 "/otr trust|untrust",
1782 "/otr secret <secret>",
1783 "/otr question <question> <answer>",
1784 "/otr answer <answer>",
1785 "/otr policy manual|opportunistic|always [<contact>]",
1786 "/otr log on|off|redact",
1787 "/otr char <char>",
1788 "/otr sendfile on|off")
1789 CMD_DESC(
1790 "Off The Record (OTR) commands to manage keys, and perform OTR encryption during chat sessions.")
1791 CMD_ARGS(
1792 { "libver", "Show which version of the libotr library is being used." },
1793 { "gen", "Generate your private key." },
1794 { "myfp", "Show your fingerprint." },
1795 { "theirfp", "Show contacts fingerprint." },
1796 { "start [<contact>]", "Start an OTR session with contact, or current recipient if omitted." },
1797 { "end", "End the current OTR session." },
1798 { "trust|untrust", "Indicate whether or not you trust the contact's fingerprint." },
1799 { "secret <secret>", "Verify a contact's identity using a shared secret." },
1800 { "question <question> <answer>", "Verify a contact's identity using a question and expected answer." },
1801 { "answer <answer>", "Respond to a question answer verification request with your answer." },
1802 { "policy manual", "Set the global OTR policy to manual, OTR sessions must be started manually." },
1803 { "policy manual <contact>", "Set the OTR policy to manual for a specific contact." },
1804 { "policy opportunistic", "Set the global OTR policy to opportunistic, an OTR session will be attempted upon starting a conversation." },
1805 { "policy opportunistic <contact>", "Set the OTR policy to opportunistic for a specific contact." },
1806 { "policy always", "Set the global OTR policy to always, an error will be displayed if an OTR session cannot be initiated upon starting a conversation." },
1807 { "policy always <contact>", "Set the OTR policy to always for a specific contact." },
1808 { "log on|off", "Enable or disable plaintext logging of OTR encrypted messages." },
1809 { "log redact", "Log OTR encrypted messages, but replace the contents with [redacted]. This is the default." },
1810 { "char <char>", "Set the character to be displayed next to OTR encrypted messages." },
1811 { "sendfile on|off", "Allow /sendfile to send unencrypted files while in an OTR session." })
1812 CMD_EXAMPLES(
1813 "/otr log off",
1814 "/otr policy manual",
1815 "/otr policy opportunistic odin@valhalla.edda",
1816 "/otr gen",
1817 "/otr start odin@valhalla.edda",
1818 "/otr myfp",
1819 "/otr theirfp",
1820 "/otr question \"What is the name of my rabbit?\" fiffi",
1821 "/otr end",
1822 "/otr char *")
1823 },
1824
1825 { "/outtype",
1826 parse_args, 1, 1, &cons_outtype_setting,
1827 CMD_NOSUBFUNCS
1828 CMD_MAINFUNC(cmd_outtype)
1829 CMD_TAGS(
1830 CMD_TAG_CHAT)
1831 CMD_SYN(
1832 "/outtype on|off")
1833 CMD_DESC(
1834 "Send typing notifications, chat states (/states) will be enabled if this setting is enabled.")
1835 CMD_ARGS(
1836 { "on|off", "Enable or disable sending typing notifications." })
1837 CMD_NOEXAMPLES
1838 },
1839
1840 { "/gone",
1841 parse_args, 1, 1, &cons_gone_setting,
1842 CMD_NOSUBFUNCS
1843 CMD_MAINFUNC(cmd_gone)
1844 CMD_TAGS(
1845 CMD_TAG_CHAT)
1846 CMD_SYN(
1847 "/gone <minutes>")
1848 CMD_DESC(
1849 "Send a 'gone' state to the recipient after the specified number of minutes. "
1850 "Chat states (/states) will be enabled if this setting is set.")
1851 CMD_ARGS(
1852 { "<minutes>", "Number of minutes of inactivity before sending the 'gone' state, a value of 0 will disable sending this state." })
1853 CMD_NOEXAMPLES
1854 },
1855
1856 { "/history",
1857 parse_args, 1, 1, &cons_history_setting,
1858 CMD_NOSUBFUNCS
1859 CMD_MAINFUNC(cmd_history)
1860 CMD_TAGS(
1861 CMD_TAG_UI,
1862 CMD_TAG_CHAT)
1863 CMD_SYN(
1864 "/history on|off")
1865 CMD_DESC(
1866 "Switch chat history on or off, /logging chat will automatically be enabled when this setting is on. "
1867 "When history is enabled, previous messages are shown in chat windows.")
1868 CMD_ARGS(
1869 { "on|off", "Enable or disable showing chat history." })
1870 CMD_NOEXAMPLES
1871 },
1872
1873 { "/log",
1874 parse_args, 1, 2, &cons_log_setting,
1875 CMD_NOSUBFUNCS
1876 CMD_MAINFUNC(cmd_log)
1877 CMD_NOTAGS
1878 CMD_SYN(
1879 "/log where",
1880 "/log rotate on|off",
1881 "/log maxsize <bytes>",
1882 "/log shared on|off")
1883 CMD_DESC(
1884 "Manage profanity log settings.")
1885 CMD_ARGS(
1886 { "where", "Show the current log file location." },
1887 { "rotate on|off", "Rotate log, default on. Does not take effect if you specified a filename yourself when starting Profanity." },
1888 { "maxsize <bytes>", "With rotate enabled, specifies the max log size, defaults to 1048580 (1MB)." },
1889 { "shared on|off", "Share logs between all instances, default: on. When off, the process id will be included in the log filename. Does not take effect if you specified a filename yourself when starting Profanity." })
1890 CMD_NOEXAMPLES
1891 },
1892
1893 { "/carbons",
1894 parse_args, 1, 1, &cons_carbons_setting,
1895 CMD_NOSUBFUNCS
1896 CMD_MAINFUNC(cmd_carbons)
1897 CMD_TAGS(
1898 CMD_TAG_CHAT)
1899 CMD_SYN(
1900 "/carbons on|off")
1901 CMD_DESC(
1902 "Enable or disable message carbons. "
1903 "Message carbons ensure that both sides of all conversations are shared with all the user's clients that implement this protocol.")
1904 CMD_ARGS(
1905 { "on|off", "Enable or disable message carbons." })
1906 CMD_NOEXAMPLES
1907 },
1908
1909 { "/receipts",
1910 parse_args, 2, 2, &cons_receipts_setting,
1911 CMD_NOSUBFUNCS
1912 CMD_MAINFUNC(cmd_receipts)
1913 CMD_TAGS(
1914 CMD_TAG_CHAT)
1915 CMD_SYN(
1916 "/receipts request on|off",
1917 "/receipts send on|off")
1918 CMD_DESC(
1919 "Enable or disable message delivery receipts. The interface will indicate when a message has been received.")
1920 CMD_ARGS(
1921 { "request on|off", "Whether or not to request a receipt upon sending a message." },
1922 { "send on|off", "Whether or not to send a receipt if one has been requested with a received message." })
1923 CMD_NOEXAMPLES
1924 },
1925
1926 { "/reconnect",
1927 parse_args, 1, 1, &cons_reconnect_setting,
1928 CMD_NOSUBFUNCS
1929 CMD_MAINFUNC(cmd_reconnect)
1930 CMD_TAGS(
1931 CMD_TAG_CONNECTION)
1932 CMD_SYN(
1933 "/reconnect <seconds>")
1934 CMD_DESC(
1935 "Set the reconnect attempt interval for when the connection is lost.")
1936 CMD_ARGS(
1937 { "<seconds>", "Number of seconds before attempting to reconnect, a value of 0 disables reconnect." })
1938 CMD_NOEXAMPLES
1939 },
1940
1941 { "/autoping",
1942 parse_args, 2, 2, &cons_autoping_setting,
1943 CMD_NOSUBFUNCS
1944 CMD_MAINFUNC(cmd_autoping)
1945 CMD_TAGS(
1946 CMD_TAG_CONNECTION)
1947 CMD_SYN(
1948 "/autoping set <seconds>",
1949 "/autoping timeout <seconds>")
1950 CMD_DESC(
1951 "Set the interval between sending ping requests to the server to ensure the connection is kept alive.")
1952 CMD_ARGS(
1953 { "set <seconds>", "Number of seconds between sending pings, a value of 0 disables autoping." },
1954 { "timeout <seconds>", "Seconds to wait for autoping responses, after which the connection is considered broken." })
1955 CMD_NOEXAMPLES
1956 },
1957
1958 { "/ping",
1959 parse_args, 0, 1, NULL,
1960 CMD_NOSUBFUNCS
1961 CMD_MAINFUNC(cmd_ping)
1962 CMD_TAGS(
1963 CMD_TAG_CONNECTION)
1964 CMD_SYN(
1965 "/ping [<jid>]")
1966 CMD_DESC(
1967 "Sends an IQ ping stanza to the specified JID. "
1968 "If no JID is supplied, your chat server will be pinged.")
1969 CMD_ARGS(
1970 { "<jid>", "The Jabber ID to send the ping request to." })
1971 CMD_NOEXAMPLES
1972 },
1973
1974 { "/autoaway",
1975 parse_args_with_freetext, 2, 3, &cons_autoaway_setting,
1976 CMD_NOSUBFUNCS
1977 CMD_MAINFUNC(cmd_autoaway)
1978 CMD_TAGS(
1979 CMD_TAG_PRESENCE)
1980 CMD_SYN(
1981 "/autoaway mode idle|away|off",
1982 "/autoaway time away|xa <minutes>",
1983 "/autoaway message away|xa <message>|off",
1984 "/autoaway check on|off")
1985 CMD_DESC(
1986 "Manage autoaway settings for idle time.")
1987 CMD_ARGS(
1988 { "mode idle", "Sends idle time, status remains online." },
1989 { "mode away", "Sends away and xa presence as well as idle time." },
1990 { "mode off", "Disabled (default)." },
1991 { "time away <minutes>", "Number of minutes before the away presence is sent, default: 15." },
1992 { "time xa <minutes>", "Number of minutes before the xa presence is sent, default: 0 (disabled)." },
1993 { "message away <message>", "Optional message to send with the away presence, default: off (disabled)." },
1994 { "message xa <message>", "Optional message to send with the xa presence, default: off (disabled)." },
1995 { "message away off", "Send no message with away presence." },
1996 { "message xa off", "Send no message with xa presence." },
1997 { "check on|off", "When enabled, checks for activity and sends online presence, default: on." })
1998 CMD_EXAMPLES(
1999 "/autoaway mode away",
2000 "/autoaway time away 30",
2001 "/autoaway message away Away from computer for a while",
2002 "/autoaway time xa 120",
2003 "/autoaway message xa Away from computer for a very long time",
2004 "/autoaway check off")
2005 },
2006
2007 { "/priority",
2008 parse_args, 1, 1, NULL,
2009 CMD_NOSUBFUNCS
2010 CMD_MAINFUNC(cmd_priority)
2011 CMD_TAGS(
2012 CMD_TAG_PRESENCE)
2013 CMD_SYN(
2014 "/priority <priority>")
2015 CMD_DESC(
2016 "Set priority for the current account. "
2017 "See the /account command for specific priority settings per presence status.")
2018 CMD_ARGS(
2019 { "<priority>", "Number between -128 and 127, default: 0." })
2020 CMD_NOEXAMPLES
2021 },
2022
2023 { "/account",
2024 parse_args, 0, 4, NULL,
2025 CMD_SUBFUNCS(
2026 { "list", cmd_account_list },
2027 { "show", cmd_account_show },
2028 { "add", cmd_account_add },
2029 { "remove", cmd_account_remove },
2030 { "enable", cmd_account_enable },
2031 { "disable", cmd_account_disable },
2032 { "rename", cmd_account_rename },
2033 { "default", cmd_account_default },
2034 { "set", cmd_account_set },
2035 { "clear", cmd_account_clear })
2036 CMD_MAINFUNC(cmd_account)
2037 CMD_TAGS(
2038 CMD_TAG_CONNECTION,
2039 CMD_TAG_PRESENCE,
2040 CMD_TAG_CHAT,
2041 CMD_TAG_GROUPCHAT)
2042 CMD_SYN(
2043 "/account",
2044 "/account list",
2045 "/account show <account>",
2046 "/account enable|disable <account>",
2047 "/account default set <account>",
2048 "/account default off",
2049 "/account add <account>",
2050 "/account remove <account>",
2051 "/account rename <account> <newaccount>",
2052 "/account set <account> jid <jid>",
2053 "/account set <account> server <server>",
2054 "/account set <account> port <port>",
2055 "/account set <account> status <presence>",
2056 "/account set <account> status last",
2057 "/account set <account> <presence> <priority>",
2058 "/account set <account> resource <resource>",
2059 "/account set <account> password <password>",
2060 "/account set <account> eval_password <command>",
2061 "/account set <account> muc <service>",
2062 "/account set <account> nick <nick>",
2063 "/account set <account> otr <policy>",
2064 "/account set <account> pgpkeyid <pgpkeyid>",
2065 "/account set <account> startscript <script>",
2066 "/account set <account> tls force|allow|trust|legacy|disable",
2067 "/account set <account> auth default|legacy",
2068 "/account set <account> theme <theme>",
2069 "/account clear <account> password",
2070 "/account clear <account> eval_password",
2071 "/account clear <account> server",
2072 "/account clear <account> port",
2073 "/account clear <account> otr",
2074 "/account clear <account> pgpkeyid",
2075 "/account clear <account> startscript",
2076 "/account clear <account> muc",
2077 "/account clear <account> resource")
2078 CMD_DESC(
2079 "Commands for creating and managing accounts. "
2080 "Calling with no arguments will display information for the current account.")
2081 CMD_ARGS(
2082 { "list", "List all accounts." },
2083 { "enable <account>", "Enable the account, it will be used for autocompletion." },
2084 { "show <account>", "Show details for the specified account." },
2085 { "disable <account>", "Disable the account." },
2086 { "default set <account>", "Set the default account, used when no argument passed to the /connect command." },
2087 { "default off", "Clear the default account setting." },
2088 { "add <account>", "Create a new account." },
2089 { "remove <account>", "Remove an account." },
2090 { "rename <account> <newaccount>", "Rename 'account' to 'newaccount'." },
2091 { "set <account> jid <jid>", "Set the Jabber ID for the account, account name will be used if not set." },
2092 { "set <account> server <server>", "The chat server, if different to the domainpart of the JID." },
2093 { "set <account> port <port>", "The port used for connecting if not the default (5222, or 5223 for SSL)." },
2094 { "set <account> status <presence>", "The presence status to use on login." },
2095 { "set <account> status last", "Use your last status before logging out, when logging in." },
2096 { "set <account> <presence> <priority>", "Set the priority (-128..127) to use for the specified presence." },
2097 { "set <account> resource <resource>", "The resource to be used for this account, defaults to 'profanity'." },
2098 { "set <account> password <password>", "Password for the account, note this is currently stored in plaintext if set." },
2099 { "set <account> eval_password <command>", "Shell command evaluated to retrieve password for the account. Can be used to retrieve password from keyring." },
2100 { "set <account> muc <service>", "The default MUC chat service to use, defaults to the servers disco info response." },
2101 { "set <account> nick <nick>", "The default nickname to use when joining chat rooms." },
2102 { "set <account> otr <policy>", "Override global OTR policy for this account, see /otr." },
2103 { "set <account> pgpkeyid <pgpkeyid>", "Set the ID of the PGP key for this account, see /pgp." },
2104 { "set <account> startscript <script>", "Set the script to execute after connecting." },
2105 { "set <account> tls force", "Force TLS connection, and fail if one cannot be established, this is default behaviour." },
2106 { "set <account> tls allow", "Use TLS for the connection if it is available." },
2107 { "set <account> tls trust", "Force TLS connection and trust server's certificate." },
2108 { "set <account> tls legacy", "Use legacy TLS for the connection. It means server doesn't support STARTTLS and TLS is forced just after TCP connection is established." },
2109 { "set <account> tls disable", "Disable TLS for the connection." },
2110 { "set <account> auth default", "Use default authentication process." },
2111 { "set <account> auth legacy", "Allow legacy authentication." },
2112 { "set <account> <theme>", "Set the UI theme for the account." },
2113 { "clear <account> server", "Remove the server setting for this account." },
2114 { "clear <account> port", "Remove the port setting for this account." },
2115 { "clear <account> password", "Remove the password setting for this account." },
2116 { "clear <account> eval_password", "Remove the eval_password setting for this account." },
2117 { "clear <account> otr", "Remove the OTR policy setting for this account." },
2118 { "clear <account> pgpkeyid", "Remove pgpkeyid associated with this account." },
2119 { "clear <account> startscript", "Remove startscript associated with this account." },
2120 { "clear <account> theme", "Clear the theme setting for the account, the global theme will be used." },
2121 { "clear <account> resource", "Remove the resource setting for this account." },
2122 { "clear <account> muc", "Remove the default MUC service setting." })
2123 CMD_EXAMPLES(
2124 "/account add me",
2125 "/account set me jid ulfhednar@valhalla.edda",
2126 "/account set me server talk.chat.com",
2127 "/account set me port 5111",
2128 "/account set me muc chatservice.mycompany.com",
2129 "/account set me nick dennis",
2130 "/account set me status dnd",
2131 "/account set me dnd -1",
2132 "/account rename me chattyme",
2133 "/account clear me pgpkeyid")
2134 },
2135
2136 { "/plugins",
2137 parse_args, 0, 3, NULL,
2138 CMD_SUBFUNCS(
2139 { "sourcepath", cmd_plugins_sourcepath },
2140 { "install", cmd_plugins_install },
2141 { "uninstall", cmd_plugins_uninstall },
2142 { "update", cmd_plugins_update },
2143 { "load", cmd_plugins_load },
2144 { "unload", cmd_plugins_unload },
2145 { "reload", cmd_plugins_reload },
2146 { "python_version", cmd_plugins_python_version })
2147 CMD_MAINFUNC(cmd_plugins)
2148 CMD_NOTAGS
2149 CMD_SYN(
2150 "/plugins",
2151 "/plugins sourcepath set <path>",
2152 "/plugins sourcepath clear",
2153 "/plugins install [<path>]",
2154 "/plugins uninstall [<plugin>]",
2155 "/plugins update [<path>]",
2156 "/plugins unload [<plugin>]",
2157 "/plugins load [<plugin>]",
2158 "/plugins reload [<plugin>]",
2159 "/plugins python_version")
2160 CMD_DESC(
2161 "Manage plugins. Passing no arguments lists currently loaded plugins.")
2162 CMD_ARGS(
2163 { "sourcepath set <path>", "Set the default path to install plugins from, will be used if no arg is passed to /plugins install." },
2164 { "sourcepath clear", "Clear the default plugins source path." },
2165 { "install [<path>]", "Install a plugin, or all plugins found in a directory (recursive). Passing no argument will use the sourcepath if one is set." },
2166 { "uninstall [<plugin>]", "Uninstall a plugin." },
2167 { "update [<path>]", "Updates an installed plugin" },
2168 { "load [<plugin>]", "Load a plugin that already exists in the plugin directory, passing no argument loads all found plugins." },
2169 { "unload [<plugin>]", "Unload a loaded plugin, passing no argument will unload all plugins." },
2170 { "reload [<plugin>]", "Reload a plugin, passing no argument will reload all plugins." },
2171 { "python_version", "Show the Python interpreter version." })
2172 CMD_EXAMPLES(
2173 "/plugins sourcepath set /home/meee/projects/profanity-plugins",
2174 "/plugins install",
2175 "/plugins install /home/steveharris/Downloads/metal.py",
2176 "/plugins update /home/steveharris/Downloads/metal.py",
2177 "/plugins uninstall browser.py",
2178 "/plugins load browser.py",
2179 "/plugins unload say.py",
2180 "/plugins reload wikipedia.py")
2181 },
2182
2183 { "/prefs",
2184 parse_args, 0, 1, NULL,
2185 CMD_NOSUBFUNCS
2186 CMD_MAINFUNC(cmd_prefs)
2187 CMD_NOTAGS
2188 CMD_SYN(
2189 "/prefs [ui|desktop|chat|log|conn|presence|otr|pgp|omemo]")
2190 CMD_DESC(
2191 "Show preferences for different areas of functionality. "
2192 "Passing no arguments shows all preferences.")
2193 CMD_ARGS(
2194 { "ui", "User interface preferences." },
2195 { "desktop", "Desktop notification preferences." },
2196 { "chat", "Chat state preferences." },
2197 { "log", "Logging preferences." },
2198 { "conn", "Connection handling preferences." },
2199 { "presence", "Chat presence preferences." },
2200 { "otr", "Off The Record preferences." },
2201 { "pgp", "OpenPGP preferences." },
2202 { "omemo", "OMEMO preferences." })
2203 CMD_NOEXAMPLES
2204 },
2205
2206 { "/theme",
2207 parse_args, 1, 2, &cons_theme_setting,
2208 CMD_NOSUBFUNCS
2209 CMD_MAINFUNC(cmd_theme)
2210 CMD_TAGS(
2211 CMD_TAG_UI)
2212 CMD_SYN(
2213 "/theme list",
2214 "/theme load <theme>",
2215 "/theme full-load <theme>",
2216 "/theme colours",
2217 "/theme properties")
2218 CMD_DESC(
2219 "Load a theme, includes colours and UI options.")
2220 CMD_ARGS(
2221 { "list", "List all available themes." },
2222 { "load <theme>", "Load colours from specified theme. 'default' will reset to the default theme." },
2223 { "full-load <theme>", "Same as 'load' but will also load preferences set in the theme, not just colours." },
2224 { "colours", "Show colour values as rendered by the terminal." },
2225 { "properties", "Show colour settings for current theme." })
2226 CMD_EXAMPLES(
2227 "/theme list",
2228 "/theme load forest")
2229 },
2230
2231 { "/xmlconsole",
2232 parse_args, 0, 0, NULL,
2233 CMD_NOSUBFUNCS
2234 CMD_MAINFUNC(cmd_xmlconsole)
2235 CMD_TAGS(
2236 CMD_TAG_UI)
2237 CMD_SYN(
2238 "/xmlconsole")
2239 CMD_DESC(
2240 "Open the XML console to view incoming and outgoing XMPP traffic.")
2241 CMD_NOARGS
2242 CMD_NOEXAMPLES
2243 },
2244
2245 { "/script",
2246 parse_args, 1, 2, NULL,
2247 CMD_NOSUBFUNCS
2248 CMD_MAINFUNC(cmd_script)
2249 CMD_NOTAGS
2250 CMD_SYN(
2251 "/script run <script>",
2252 "/script list",
2253 "/script show <script>")
2254 CMD_DESC(
2255 "Run command scripts. "
2256 "Scripts are stored in $XDG_DATA_HOME/profanity/scripts/ which is usually $HOME/.local/share/profanity/scripts/.")
2257 CMD_ARGS(
2258 { "script run <script>", "Execute a script." },
2259 { "script list", "List all scripts TODO." },
2260 { "script show <script>", "Show the commands in script TODO." })
2261 CMD_EXAMPLES(
2262 "/script list",
2263 "/script run myscript",
2264 "/script show somescript")
2265 },
2266
2267 { "/export",
2268 parse_args, 1, 1, NULL,
2269 CMD_NOSUBFUNCS
2270 CMD_MAINFUNC(cmd_export)
2271 CMD_NOTAGS
2272 CMD_SYN(
2273 "/export <filepath>")
2274 CMD_DESC(
2275 "Exports contacts to a csv file.")
2276 CMD_ARGS(
2277 { "<filepath>", "Path to the output file." })
2278 CMD_EXAMPLES(
2279 "/export /path/to/output.csv",
2280 "/export ~/contacts.csv")
2281 },
2282
2283 { "/cmd",
2284 parse_args, 1, 3, NULL,
2285 CMD_SUBFUNCS(
2286 { "list", cmd_command_list },
2287 { "exec", cmd_command_exec })
2288 CMD_NOMAINFUNC
2289 CMD_NOTAGS
2290 CMD_SYN(
2291 "/cmd list [<jid>]",
2292 "/cmd exec <command> [<jid>]")
2293 CMD_DESC(
2294 "Execute ad hoc commands.")
2295 CMD_ARGS(
2296 { "list", "List supported ad hoc commands." },
2297 { "exec <command>", "Execute a command." })
2298 CMD_EXAMPLES(
2299 "/cmd list",
2300 "/cmd exec ping")
2301 },
2302
2303 { "/omemo",
2304 parse_args, 1, 3, NULL,
2305 CMD_SUBFUNCS(
2306 { "gen", cmd_omemo_gen },
2307 { "log", cmd_omemo_log },
2308 { "start", cmd_omemo_start },
2309 { "end", cmd_omemo_end },
2310 { "trustmode", cmd_omemo_trust_mode },
2311 { "trust", cmd_omemo_trust },
2312 { "untrust", cmd_omemo_untrust },
2313 { "fingerprint", cmd_omemo_fingerprint },
2314 { "char", cmd_omemo_char },
2315 { "policy", cmd_omemo_policy },
2316 { "clear_device_list", cmd_omemo_clear_device_list })
2317 CMD_NOMAINFUNC
2318 CMD_TAGS(
2319 CMD_TAG_CHAT,
2320 CMD_TAG_UI)
2321 CMD_SYN(
2322 "/omemo gen",
2323 "/omemo log on|off|redact",
2324 "/omemo start [<contact>]",
2325 "/omemo trust [<contact>] <fingerprint>",
2326 "/omemo end",
2327 "/omemo fingerprint [<contact>]",
2328 "/omemo char <char>",
2329 "/omemo trustmode manual|firstusage|blind",
2330 "/omemo policy manual|automatic|always",
2331 "/omemo clear_device_list")
2332 CMD_DESC(
2333 "OMEMO commands to manage keys, and perform encryption during chat sessions.")
2334 CMD_ARGS(
2335 { "gen", "Generate OMEMO crytographic materials for current account." },
2336 { "start [<contact>]", "Start an OMEMO session with contact, or current recipient if omitted." },
2337 { "end", "End the current OMEMO session." },
2338 { "log on|off", "Enable or disable plaintext logging of OMEMO encrypted messages." },
2339 { "log redact", "Log OMEMO encrypted messages, but replace the contents with [redacted]. This is the default." },
2340 { "fingerprint [<contact>]", "Show contact fingerprints, or current recipient if omitted." },
2341 { "char <char>", "Set the character to be displayed next to OMEMO encrypted messages." },
2342 { "trustmode manual", "Set the global OMEMO trust mode to manual, OMEMO keys has to be trusted manually." },
2343 { "trustmode firstusage", "Set the global OMEMO trust mode to ToFu, first OMEMO keys trusted automatically." },
2344 { "trustmode blind", "Set the global OMEMO trust mode to blind, ALL OMEMO keys trusted automatically." },
2345 { "policy manual", "Set the global OMEMO policy to manual, OMEMO sessions must be started manually." },
2346 { "policy automatic", "Set the global OMEMO policy to opportunistic, an OMEMO session will be attempted upon starting a conversation." },
2347 { "policy always", "Set the global OMEMO policy to always, an error will be displayed if an OMEMO session cannot be initiated upon starting a conversation." },
2348 { "clear_device_list", "Clear your own device list on server side. Each client will reannounce itself when connected back."})
2349 CMD_EXAMPLES(
2350 "/omemo gen",
2351 "/omemo start odin@valhalla.edda",
2352 "/omemo trust c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a",
2353 "/omemo untrust loki@valhalla.edda c4f9c875-144d7a3b-0c4a05b6-ca3be51a-a037f329-0bd3ae62-07f99719-55559d2a",
2354 "/omemo char *")
2355 },
2356
2357 { "/save",
2358 parse_args, 0, 0, NULL,
2359 CMD_NOSUBFUNCS
2360 CMD_MAINFUNC(cmd_save)
2361 CMD_NOTAGS
2362 CMD_SYN(
2363 "/save")
2364 CMD_DESC(
2365 "Save preferences to configuration file.")
2366 CMD_NOARGS
2367 CMD_NOEXAMPLES
2368 },
2369
2370 { "/reload",
2371 parse_args, 0, 0, NULL,
2372 CMD_NOSUBFUNCS
2373 CMD_MAINFUNC(cmd_reload)
2374 CMD_NOTAGS
2375 CMD_SYN(
2376 "/reload")
2377 CMD_DESC(
2378 "Reload preferences from configuration file.")
2379 CMD_NOARGS
2380 CMD_NOEXAMPLES
2381 },
2382
2383 { "/paste",
2384 parse_args, 0, 0, NULL,
2385 CMD_NOSUBFUNCS
2386 CMD_MAINFUNC(cmd_paste)
2387 CMD_NOTAGS
2388 CMD_SYN(
2389 "/paste")
2390 CMD_DESC(
2391 "Paste clipboard.")
2392 CMD_NOARGS
2393 CMD_NOEXAMPLES
2394 },
2395
2396 { "/color",
2397 parse_args, 1, 2, &cons_color_setting,
2398 CMD_NOSUBFUNCS
2399 CMD_MAINFUNC(cmd_color)
2400 CMD_TAGS(
2401 CMD_TAG_UI)
2402 CMD_SYN(
2403 "/color on|off|redgreen|blue",
2404 "/color own on|off")
2405 CMD_DESC(
2406 "Settings for consistent color generation for nicks (XEP-0392). Including corrections for Color Vision Deficiencies. "
2407 "Your terminal needs to support 256 colors.")
2408 CMD_ARGS(
2409 { "on|off|redgreen|blue", "Enable or disable nick colorization for MUC nicks. 'redgreen' is for people with red/green blindness and 'blue' for people with blue blindness." },
2410 { "own on|off", "Enable color generation for own nick. If disabled the color from the color from the theme ('me') will get used." })
2411 CMD_EXAMPLES(
2412 "/color off",
2413 "/color on",
2414 "/color blue",
2415 "/color own off")
2416 },
2417
2418 { "/avatar",
2419 parse_args, 2, 2, NULL,
2420 CMD_NOSUBFUNCS
2421 CMD_MAINFUNC(cmd_avatar)
2422 CMD_TAGS(
2423 CMD_TAG_CHAT)
2424 CMD_SYN(
2425 "/avatar get <barejid>",
2426 "/avatar open <barejid>")
2427 CMD_DESC(
2428 "Download avatar (XEP-0084) for a certain contact. "
2429 "If nothing happens after using this command the user either doesn't have an avatar set at all "
2430 "or doesn't use XEP-0084 to publish it.")
2431 CMD_ARGS(
2432 { "get <barejid>", "Download the avatar. barejid is the JID to download avatar from." },
2433 { "open <barejid>", "Download avatar and open it with command." })
2434 CMD_EXAMPLES(
2435 "/avatar get thor@valhalla.edda",
2436 "/avatar open freyja@vanaheimr.edda") },
2437
2438 { "/os",
2439 parse_args, 1, 1, &cons_os_setting,
2440 CMD_NOSUBFUNCS
2441 CMD_MAINFUNC(cmd_os)
2442 CMD_TAGS(
2443 CMD_TAG_DISCOVERY)
2444 CMD_SYN(
2445 "/os <on>|<off>")
2446 CMD_DESC(
2447 "Choose whether to include the OS name if a user asks for software information (XEP-0092).")
2448 CMD_ARGS(
2449 { "on|off", "" })
2450 CMD_NOEXAMPLES
2451 },
2452
2453 { "/correction",
2454 parse_args, 1, 2, &cons_correction_setting,
2455 CMD_NOSUBFUNCS
2456 CMD_MAINFUNC(cmd_correction)
2457 CMD_TAGS(
2458 CMD_TAG_UI,
2459 CMD_TAG_CHAT,
2460 CMD_TAG_GROUPCHAT)
2461 CMD_SYN(
2462 "/correction <on>|<off>",
2463 "/correction char <char>")
2464 CMD_DESC(
2465 "Settings regarding Last Message Correction (XEP-0308). "
2466 "Corrections will only work in MUC and regular chat windows. MUC PMs won't be allowed. "
2467 "For more information on how to correct messages, see: /help correct.")
2468 CMD_ARGS(
2469 { "on|off", "Enable/Disable support for last message correction." },
2470 { "char", "Set character that will prefix corrected messages. Default: '+'." })
2471 CMD_NOEXAMPLES
2472 },
2473
2474 { "/correct",
2475 parse_args_as_one, 1, 1, NULL,
2476 CMD_NOSUBFUNCS
2477 CMD_MAINFUNC(cmd_correct)
2478 CMD_TAGS(
2479 CMD_TAG_CHAT,
2480 CMD_TAG_GROUPCHAT)
2481 CMD_SYN(
2482 "/correct <message>")
2483 CMD_DESC(
2484 "Correct and resend the last message (XEP-0308). "
2485 "Use tab completion to get the last sent message. "
2486 "For more information on how to configure corrections, see: /help correction.")
2487 CMD_ARGS(
2488 { "message", "The corrected message." })
2489 CMD_NOEXAMPLES
2490 },
2491
2492 { "/slashguard",
2493 parse_args, 1, 1, &cons_slashguard_setting,
2494 CMD_NOSUBFUNCS
2495 CMD_MAINFUNC(cmd_slashguard)
2496 CMD_TAGS(
2497 CMD_TAG_UI,
2498 CMD_TAG_CHAT)
2499 CMD_SYN(
2500 "/slashguard on|off")
2501 CMD_DESC(
2502 "Slashguard won't accept a slash in the first 4 characters of your input field. "
2503 "It tries to protect you from typing ' /quit' and similar things in chats.")
2504 CMD_ARGS(
2505 { "on|off", "Enable or disable slashguard." })
2506 CMD_NOEXAMPLES
2507 },
2508
2509 { "/serversoftware",
2510 parse_args, 1, 1, NULL,
2511 CMD_NOSUBFUNCS
2512 CMD_MAINFUNC(cmd_serversoftware)
2513 CMD_TAGS(
2514 CMD_TAG_DISCOVERY)
2515 CMD_SYN(
2516 "/serversoftware <domain>")
2517 CMD_DESC(
2518 "Find server or component software version information.")
2519 CMD_ARGS(
2520 { "<domain>", "The jid of your server or component." })
2521 CMD_EXAMPLES(
2522 "/serversoftware valhalla.edda",
2523 "/serversoftware xmpp.vanaheimr.edda")
2524 },
2525
2526 { "/executable",
2527 parse_args, 2, 4, &cons_executable_setting,
2528 CMD_SUBFUNCS(
2529 { "avatar", cmd_executable_avatar },
2530 { "urlopen", cmd_executable_urlopen },
2531 { "urlsave", cmd_executable_urlsave },
2532 { "editor", cmd_executable_editor })
2533 CMD_NOMAINFUNC
2534 CMD_TAGS(
2535 CMD_TAG_DISCOVERY)
2536 CMD_SYN(
2537 "/executable avatar <cmd>",
2538 "/executable urlopen set <cmdtemplate>",
2539 "/executable urlopen default",
2540 "/executable urlsave set <cmdtemplate>",
2541 "/executable urlsave default")
2542 CMD_DESC(
2543 "Configure executable that should be called upon a certain command.")
2544 CMD_ARGS(
2545 { "avatar", "Set executable that is run by /avatar open. Use your favorite image viewer." },
2546 { "urlopen set", "Set executable that is run by /url open. Takes a command template that replaces %u and %p with the URL and path respectively." },
2547 { "urlopen default", "Restore to default settings." },
2548 { "urlsave set", "Set executable that is run by /url save. Takes a command template that replaces %u and %p with the URL and path respectively." },
2549 { "urlsave default", "Use the built-in download method for saving." },
2550 { "editor set", "Set editor to be used with /editor. Needs a terminal editor or a script to run a graphical editor." })
2551 CMD_EXAMPLES(
2552 "/executable avatar xdg-open",
2553 "/executable urlopen set \"xdg-open %u\"",
2554 "/executable urlopen set \"firefox %u\"",
2555 "/executable urlopen default",
2556 "/executable urlsave set \"wget %u -O %p\"",
2557 "/executable urlsave set \"curl %u -o %p\"",
2558 "/executable urlsave default",
2559 "/executable editor set vim")
2560 },
2561
2562 { "/url",
2563 parse_args, 2, 3, NULL,
2564 CMD_SUBFUNCS(
2565 { "open", cmd_url_open },
2566 { "save", cmd_url_save })
2567 CMD_NOMAINFUNC
2568 CMD_TAGS(
2569 CMD_TAG_CHAT,
2570 CMD_TAG_GROUPCHAT)
2571 CMD_SYN(
2572 "/url open <url>",
2573 "/url save <url> [<path>]")
2574 CMD_DESC(
2575 "Deal with URLs")
2576 CMD_ARGS(
2577 { "open", "Open URL with predefined executable." },
2578 { "save", "Save URL to optional path, default path is current directory" })
2579 CMD_EXAMPLES(
2580 "/url open https://profanity-im.github.io",
2581 "/url save https://profanity-im.github.io/guide/latest/userguide.html /home/user/Download/")
2582 },
2583
2584 { "/mam",
2585 parse_args, 1, 1, &cons_mam_setting,
2586 CMD_NOSUBFUNCS
2587 CMD_MAINFUNC(cmd_mam)
2588 CMD_TAGS(
2589 CMD_TAG_CHAT)
2590 CMD_SYN(
2591 "/mam <on>|<off>")
2592 CMD_DESC(
2593 "Enable/Disable Message Archive Management (XEP-0313) "
2594 "MAM is in experimental state. For regular users there are still many confusing things when enabling this feature. "
2595 "We are going to work on this in future releases. So far this setting is mostly here for developers.")
2596 CMD_ARGS(
2597 { "on|off", "Enable or disable MAM" })
2598 CMD_NOEXAMPLES
2599 },
2600
2601 { "/changepassword",
2602 parse_args, 0, 0, NULL,
2603 CMD_NOSUBFUNCS
2604 CMD_MAINFUNC(cmd_change_password)
2605 CMD_NOTAGS
2606 CMD_SYN(
2607 "/changepassword")
2608 CMD_DESC(
2609 "Change password of logged in account")
2610 CMD_NOARGS
2611 CMD_NOEXAMPLES
2612 },
2613
2614 { "/editor",
2615 parse_args, 0, 0, NULL,
2616 CMD_NOSUBFUNCS
2617 CMD_MAINFUNC(cmd_editor)
2618 CMD_TAGS(
2619 CMD_TAG_CHAT,
2620 CMD_TAG_GROUPCHAT)
2621 CMD_SYN(
2622 "/editor")
2623 CMD_DESC(
2624 "Spawn external editor to edit message. "
2625 "After editing the inputline may appear empty. Press enter to send the text anyways. "
2626 "Use /executable to set your favourite editor." )
2627 CMD_NOARGS
2628 CMD_NOEXAMPLES
2629 },
2630
2631 { "/silence",
2632 parse_args, 1, 1, &cons_silence_setting,
2633 CMD_NOSUBFUNCS
2634 CMD_MAINFUNC(cmd_silence)
2635 CMD_TAGS(
2636 CMD_TAG_CHAT)
2637 CMD_SYN(
2638 "/silence on|off")
2639 CMD_DESC(
2640 "Let's you silence all message attempts from people who are not in your roster.")
2641 CMD_NOARGS
2642 CMD_NOEXAMPLES
2643 },
2644
2645 // NEXT-COMMAND (search helper)
2646 };
2647
2648 // clang-format on
2649
2650 static GHashTable* search_index;
2651
2652 char*
_cmd_index(Command * cmd)2653 _cmd_index(Command* cmd)
2654 {
2655 GString* index_source = g_string_new("");
2656 index_source = g_string_append(index_source, cmd->cmd);
2657 index_source = g_string_append(index_source, " ");
2658 index_source = g_string_append(index_source, cmd->help.desc);
2659 index_source = g_string_append(index_source, " ");
2660
2661 int len = g_strv_length(cmd->help.tags);
2662 for (int i = 0; i < len; i++) {
2663 index_source = g_string_append(index_source, cmd->help.tags[i]);
2664 index_source = g_string_append(index_source, " ");
2665 }
2666 len = g_strv_length(cmd->help.synopsis);
2667 for (int i = 0; i < len; i++) {
2668 index_source = g_string_append(index_source, cmd->help.synopsis[i]);
2669 index_source = g_string_append(index_source, " ");
2670 }
2671 for (int i = 0; cmd->help.args[i][0] != NULL; i++) {
2672 index_source = g_string_append(index_source, cmd->help.args[i][0]);
2673 index_source = g_string_append(index_source, " ");
2674 index_source = g_string_append(index_source, cmd->help.args[i][1]);
2675 index_source = g_string_append(index_source, " ");
2676 }
2677
2678 gchar** tokens = g_str_tokenize_and_fold(index_source->str, NULL, NULL);
2679 g_string_free(index_source, TRUE);
2680
2681 GString* index = g_string_new("");
2682 for (int i = 0; i < g_strv_length(tokens); i++) {
2683 index = g_string_append(index, tokens[i]);
2684 index = g_string_append(index, " ");
2685 }
2686 g_strfreev(tokens);
2687
2688 char* res = index->str;
2689 g_string_free(index, FALSE);
2690
2691 return res;
2692 }
2693
2694 GList*
cmd_search_index_any(char * term)2695 cmd_search_index_any(char* term)
2696 {
2697 GList* results = NULL;
2698
2699 gchar** processed_terms = g_str_tokenize_and_fold(term, NULL, NULL);
2700 int terms_len = g_strv_length(processed_terms);
2701
2702 for (int i = 0; i < terms_len; i++) {
2703 GList* index_keys = g_hash_table_get_keys(search_index);
2704 GList* curr = index_keys;
2705 while (curr) {
2706 char* index_entry = g_hash_table_lookup(search_index, curr->data);
2707 if (g_str_match_string(processed_terms[i], index_entry, FALSE)) {
2708 results = g_list_append(results, curr->data);
2709 }
2710 curr = g_list_next(curr);
2711 }
2712 g_list_free(index_keys);
2713 }
2714
2715 g_strfreev(processed_terms);
2716
2717 return results;
2718 }
2719
2720 GList*
cmd_search_index_all(char * term)2721 cmd_search_index_all(char* term)
2722 {
2723 GList* results = NULL;
2724
2725 gchar** terms = g_str_tokenize_and_fold(term, NULL, NULL);
2726 int terms_len = g_strv_length(terms);
2727
2728 GList* commands = g_hash_table_get_keys(search_index);
2729 GList* curr = commands;
2730 while (curr) {
2731 char* command = curr->data;
2732 int matches = 0;
2733 for (int i = 0; i < terms_len; i++) {
2734 char* command_index = g_hash_table_lookup(search_index, command);
2735 if (g_str_match_string(terms[i], command_index, FALSE)) {
2736 matches++;
2737 }
2738 }
2739 if (matches == terms_len) {
2740 results = g_list_append(results, command);
2741 }
2742 curr = g_list_next(curr);
2743 }
2744
2745 g_list_free(commands);
2746 g_strfreev(terms);
2747
2748 return results;
2749 }
2750
2751 /*
2752 * Initialise command autocompleter and history
2753 */
2754 void
cmd_init(void)2755 cmd_init(void)
2756 {
2757 log_info("Initialising commands");
2758
2759 cmd_ac_init();
2760
2761 search_index = g_hash_table_new_full(g_str_hash, g_str_equal, free, g_free);
2762
2763 // load command defs into hash table
2764 commands = g_hash_table_new(g_str_hash, g_str_equal);
2765 for (unsigned int i = 0; i < ARRAY_SIZE(command_defs); i++) {
2766 Command* pcmd = command_defs + i;
2767
2768 // add to hash
2769 g_hash_table_insert(commands, pcmd->cmd, pcmd);
2770
2771 // add to search index
2772 g_hash_table_insert(search_index, strdup(pcmd->cmd), _cmd_index(pcmd));
2773
2774 // add to commands and help autocompleters
2775 cmd_ac_add_cmd(pcmd);
2776 }
2777
2778 // load aliases
2779 GList* aliases = prefs_get_aliases();
2780 GList* curr = aliases;
2781 while (curr) {
2782 ProfAlias* alias = curr->data;
2783 cmd_ac_add_alias(alias);
2784 curr = g_list_next(curr);
2785 }
2786 prefs_free_aliases(aliases);
2787 }
2788
2789 void
cmd_uninit(void)2790 cmd_uninit(void)
2791 {
2792 cmd_ac_uninit();
2793 g_hash_table_destroy(search_index);
2794 }
2795
2796 gboolean
cmd_valid_tag(const char * const str)2797 cmd_valid_tag(const char* const str)
2798 {
2799 return ((g_strcmp0(str, CMD_TAG_CHAT) == 0) || (g_strcmp0(str, CMD_TAG_GROUPCHAT) == 0) || (g_strcmp0(str, CMD_TAG_PRESENCE) == 0) || (g_strcmp0(str, CMD_TAG_ROSTER) == 0) || (g_strcmp0(str, CMD_TAG_DISCOVERY) == 0) || (g_strcmp0(str, CMD_TAG_CONNECTION) == 0) || (g_strcmp0(str, CMD_TAG_UI) == 0) || (g_strcmp0(str, CMD_TAG_PLUGINS) == 0));
2800 }
2801
2802 Command*
cmd_get(const char * const command)2803 cmd_get(const char* const command)
2804 {
2805 if (commands) {
2806 return g_hash_table_lookup(commands, command);
2807 } else {
2808 return NULL;
2809 }
2810 }
2811
2812 GList*
cmd_get_ordered(const char * const tag)2813 cmd_get_ordered(const char* const tag)
2814 {
2815 GList* ordered_commands = NULL;
2816
2817 GHashTableIter iter;
2818 gpointer key;
2819 gpointer value;
2820
2821 g_hash_table_iter_init(&iter, commands);
2822 while (g_hash_table_iter_next(&iter, &key, &value)) {
2823 Command* pcmd = (Command*)value;
2824 if (tag) {
2825 if (_cmd_has_tag(pcmd, tag)) {
2826 ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0);
2827 }
2828 } else {
2829 ordered_commands = g_list_insert_sorted(ordered_commands, pcmd->cmd, (GCompareFunc)g_strcmp0);
2830 }
2831 }
2832
2833 return ordered_commands;
2834 }
2835
2836 static gboolean
_cmd_has_tag(Command * pcmd,const char * const tag)2837 _cmd_has_tag(Command* pcmd, const char* const tag)
2838 {
2839 for (int i = 0; pcmd->help.tags[i] != NULL; i++) {
2840 if (g_strcmp0(tag, pcmd->help.tags[i]) == 0) {
2841 return TRUE;
2842 }
2843 }
2844
2845 return FALSE;
2846 }
2847
2848 static int
_cmp_command(Command * cmd1,Command * cmd2)2849 _cmp_command(Command* cmd1, Command* cmd2)
2850 {
2851 return g_strcmp0(cmd1->cmd, cmd2->cmd);
2852 }
2853
2854 void
command_docgen(void)2855 command_docgen(void)
2856 {
2857 GList* cmds = NULL;
2858
2859 for (unsigned int i = 0; i < ARRAY_SIZE(command_defs); i++) {
2860 Command* pcmd = command_defs + i;
2861 cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command);
2862 }
2863
2864 FILE* toc_fragment = fopen("toc_fragment.html", "w");
2865 FILE* main_fragment = fopen("main_fragment.html", "w");
2866
2867 fputs("<ul><li><ul><li>\n", toc_fragment);
2868 fputs("<hr>\n", main_fragment);
2869
2870 GList* curr = cmds;
2871 while (curr) {
2872 Command* pcmd = curr->data;
2873
2874 fprintf(toc_fragment, "<a href=\"#%s\">%s</a>,\n", &pcmd->cmd[1], pcmd->cmd);
2875 fprintf(main_fragment, "<a name=\"%s\"></a>\n", &pcmd->cmd[1]);
2876 fprintf(main_fragment, "<h4>%s</h4>\n", pcmd->cmd);
2877
2878 fputs("<p><b>Synopsis</b></p>\n", main_fragment);
2879 fputs("<p><pre><code>", main_fragment);
2880 int i = 0;
2881 while (pcmd->help.synopsis[i]) {
2882 char* str1 = str_replace(pcmd->help.synopsis[i], "<", "<");
2883 char* str2 = str_replace(str1, ">", ">");
2884 fprintf(main_fragment, "%s\n", str2);
2885 i++;
2886 }
2887 fputs("</code></pre></p>\n", main_fragment);
2888
2889 fputs("<p><b>Description</b></p>\n", main_fragment);
2890 fputs("<p>", main_fragment);
2891 fprintf(main_fragment, "%s\n", pcmd->help.desc);
2892 fputs("</p>\n", main_fragment);
2893
2894 if (pcmd->help.args[0][0] != NULL) {
2895 fputs("<p><b>Arguments</b></p>\n", main_fragment);
2896 fputs("<table>", main_fragment);
2897 for (i = 0; pcmd->help.args[i][0] != NULL; i++) {
2898 fputs("<tr>", main_fragment);
2899 fputs("<td>", main_fragment);
2900 fputs("<code>", main_fragment);
2901 char* str1 = str_replace(pcmd->help.args[i][0], "<", "<");
2902 char* str2 = str_replace(str1, ">", ">");
2903 fprintf(main_fragment, "%s", str2);
2904 fputs("</code>", main_fragment);
2905 fputs("</td>", main_fragment);
2906 fputs("<td>", main_fragment);
2907 fprintf(main_fragment, "%s", pcmd->help.args[i][1]);
2908 fputs("</td>", main_fragment);
2909 fputs("</tr>", main_fragment);
2910 }
2911 fputs("</table>\n", main_fragment);
2912 }
2913
2914 if (pcmd->help.examples[0] != NULL) {
2915 fputs("<p><b>Examples</b></p>\n", main_fragment);
2916 fputs("<p><pre><code>", main_fragment);
2917 int i = 0;
2918 while (pcmd->help.examples[i]) {
2919 fprintf(main_fragment, "%s\n", pcmd->help.examples[i]);
2920 i++;
2921 }
2922 fputs("</code></pre></p>\n", main_fragment);
2923 }
2924
2925 fputs("<a href=\"#top\"><h5>back to top</h5></a><br><hr>\n", main_fragment);
2926 fputs("\n", main_fragment);
2927
2928 curr = g_list_next(curr);
2929 }
2930
2931 fputs("</ul></ul>\n", toc_fragment);
2932
2933 fclose(toc_fragment);
2934 fclose(main_fragment);
2935 printf("\nProcessed %d commands.\n\n", g_list_length(cmds));
2936 g_list_free(cmds);
2937 }
2938
2939 void
command_mangen(void)2940 command_mangen(void)
2941 {
2942 GList* cmds = NULL;
2943
2944 for (unsigned int i = 0; i < ARRAY_SIZE(command_defs); i++) {
2945 Command* pcmd = command_defs + i;
2946 cmds = g_list_insert_sorted(cmds, pcmd, (GCompareFunc)_cmp_command);
2947 }
2948
2949 mkdir_recursive("docs");
2950
2951 GDateTime* now = g_date_time_new_now_local();
2952 gchar* date = g_date_time_format(now, "%F");
2953 gchar* header = g_strdup_printf(".TH man 1 \"%s\" \"" PACKAGE_VERSION "\" \"Profanity XMPP client\"\n", date);
2954 if (!header) {
2955 log_error("command_mangen(): could not allocate memory");
2956 return;
2957 }
2958 g_date_time_unref(now);
2959 g_free(date);
2960
2961 GList* curr = cmds;
2962 while (curr) {
2963 Command* pcmd = curr->data;
2964
2965 gchar* filename = g_strdup_printf("docs/profanity-%s.1", &pcmd->cmd[1]);
2966 if (!filename) {
2967 log_error("command_mangen(): could not allocate memory");
2968 return;
2969 }
2970 FILE* manpage = fopen(filename, "w");
2971 free(filename);
2972
2973 fprintf(manpage, "%s\n", header);
2974 fputs(".SH NAME\n", manpage);
2975 fprintf(manpage, "%s\n", pcmd->cmd);
2976
2977 fputs("\n.SH DESCRIPTION\n", manpage);
2978 fprintf(manpage, "%s\n", pcmd->help.desc);
2979
2980 fputs("\n.SH SYNOPSIS\n", manpage);
2981 int i = 0;
2982 while (pcmd->help.synopsis[i]) {
2983 fprintf(manpage, "%s\n", pcmd->help.synopsis[i]);
2984 fputs("\n.LP\n", manpage);
2985 i++;
2986 }
2987
2988 if (pcmd->help.args[0][0] != NULL) {
2989 fputs("\n.SH ARGUMENTS\n", manpage);
2990 for (i = 0; pcmd->help.args[i][0] != NULL; i++) {
2991 fprintf(manpage, ".PP\n\\fB%s\\fR\n", pcmd->help.args[i][0]);
2992 fprintf(manpage, ".RS 4\n%s\n.RE\n", pcmd->help.args[i][1]);
2993 }
2994 }
2995
2996 if (pcmd->help.examples[0] != NULL) {
2997 fputs("\n.SH EXAMPLES\n", manpage);
2998 int i = 0;
2999 while (pcmd->help.examples[i]) {
3000 fprintf(manpage, "%s\n", pcmd->help.examples[i]);
3001 fputs("\n.LP\n", manpage);
3002 i++;
3003 }
3004 }
3005
3006 fclose(manpage);
3007 curr = g_list_next(curr);
3008 }
3009
3010 printf("\nProcessed %d commands.\n\n", g_list_length(cmds));
3011
3012 g_free(header);
3013 g_list_free(cmds);
3014 }
3015