Mercurial > irccd
changeset 372:6a7850696b86
Irccdctl: rework a bit how aliases are defined to allow better arguments parsing
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 08 Dec 2016 13:15:37 +0100 |
parents | c6fb00344c19 |
children | 2a9805acb178 |
files | doc/html/irccdctl/configuring.md doc/man/irccdctl.conf.5.in irccdctl/main.cpp |
diffstat | 3 files changed, 115 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/html/irccdctl/configuring.md Wed Dec 07 12:33:32 2016 +0100 +++ b/doc/html/irccdctl/configuring.md Thu Dec 08 13:15:37 2016 +0100 @@ -58,3 +58,53 @@ type = "unix" path = "/tmp/irccd.sock" ```` + +# The alias section + +The alias section can be used to define custom user commands. + +To define an alias, just add a new section named `[alias.name]` where name is +your desired alias name. + +Then, add any option you like to execute commands you want. The option name is +ignored and serves as auto-documentation only. + +Example: + +````ini +[alias.present] +say-hello = ( "server-message", "localhost", "#staff", "hello world!" ) +warning = ( "server-me", "localhost", "#staff", "is a bot") +```` + +This example defines an alias `present` that will: + + 1. Send a message on the channel #staff in the server localhost + 2. Send an action emote on the same channel + +To use this alias, call `irccdctl present`. + +## Placeholders + +Sometimes, you want to pass parameters to your alias. The placeholder syntax +allows you to define where your command line arguments will be replaced before +being sent to irccd. + +The syntax uses `%n` where **n** is an integer starting from 0. + +As you have seen in the `present` alias example above, the channel and server +are hardcoded so the user is not able to use this alias for different channels. +Let's update this alias with placeholders to make it more generic. + +Example: + +````ini +[alias.present] +say-hello = ( "server-message", "%0", "%1", "hello world!" ) +warning = ( "server-me", "%0", "%1", "is a bot") +```` + +Now, the `present` alias will except two arguments from the command line when +the user invokes `irccdctl present`. Thus if you want to use this alias on the +**#staff@localhost**, you call the alias using +`irccdctl present localhost #staff`
--- a/doc/man/irccdctl.conf.5.in Wed Dec 07 12:33:32 2016 +0100 +++ b/doc/man/irccdctl.conf.5.in Thu Dec 08 13:15:37 2016 +0100 @@ -85,6 +85,38 @@ .It path (string) the file path to the socket. .El +.\" ALIAS +.Ss alias +The alias section can be used to define custom user commands. +.Pp +To define an alias, just add a new section named +.Nm alias.name +where name is your desired alias name. +.Pp +Then, add any option you like to execute commands you want. The option name is +ignored and serves as auto-documentation only. +.Pp +Example: +.Bd -literal +[alias.present] +say-hello = ( "server-message", "localhost", "#staff", "hello world!" ) +warning = ( "server-me", "localhost", "#staff", "is a bot") +.Ed +.Pp +.Nm Placeholders +.Pp +Sometimes, you want to pass parameters to your alias. The placeholder syntax +allows you to define where your command line arguments will be replaced before +being sent to irccd. +.Pp +The syntax uses `%n` where **n** is an integer starting from 0. +.Pp +Example: +.Bd -literal +[alias.present] +say-hello = ( "server-message", "%0", "%1", "hello world!" ) +warning = ( "server-me", "%0", "%1", "is a bot") +.Ed .\" FILES .Sh FILES The default config file is located at
--- a/irccdctl/main.cpp Wed Dec 07 12:33:32 2016 +0100 +++ b/irccdctl/main.cpp Thu Dec 08 13:15:37 2016 +0100 @@ -222,37 +222,39 @@ } /* - * readAliases + * readAlias * ------------------------------------------------------------------- * * Read aliases for irccdctl. * - * [alias] - * name = ( "command", "arg1, "...", "argn" ) + * [alias.<name>] + * cmd1 = ( "command", "arg1, "...", "argn" ) + * cmd2 = ( "command", "arg1, "...", "argn" ) */ -void readAliases(const ini::Section &sc) +Alias readAlias(const ini::Section &sc, const std::string &name) { - for (const auto &option : sc) { - // This is the alias name. - Alias alias(option.key()); + Alias alias(name); - // Iterate over the list of commands to execute for this alias. - for (const auto &repl : option) { - // This is the alias split string. - auto list = util::split(repl, " \t"); - - if (list.size() < 1) - throw std::invalid_argument("alias require at least one argument"); - - // First argument is the command/alias to execute. - auto command = list[0]; - - // Remove command name and puts arguments. - alias.push_back({std::move(command), std::vector<AliasArg>(list.begin() + 1, list.end())}); + /* + * Each defined option is a command that the user can call. The name is + * unused and serves as documentation purpose. + */ + for (const auto &option : sc) { + /* + * Iterate over the arguments which are usually a list and the first + * argument is a command name. + */ + if (option.size() == 1 && option[0].empty()) { + throw std::runtime_error("alias {}: missing command name in '{}'"_format(name, option.key())); } - aliases.emplace(option.key(), std::move(alias)); + std::string command = option[0]; + std::vector<AliasArg> args(option.begin() + 1, option.end()); + + alias.emplace_back(std::move(command), std::move(args)); } + + return alias; } void read(const std::string &path) @@ -265,8 +267,16 @@ readConnect(*it); if ((it = doc.find("general")) != doc.end()) readGeneral(*it); - if ((it = doc.find("alias")) != doc.end()) - readAliases(*it); + + // [alias.*] sections. + for (const auto& sc : doc) { + if (sc.key().compare(0, 6, "alias.") == 0) { + auto name = sc.key().substr(6); + auto alias = readAlias(sc, name); + + aliases.emplace(std::move(name), std::move(alias)); + } + } } catch (const std::exception &ex) { log::warning() << path << ": " << ex.what() << std::endl; }