templatecmd.c
author Myhailo Danylenko <isbear@ukrpost.net>
Thu, 30 Jun 2011 16:23:20 +0300
changeset 16 e7c65942ce5c
parent 14 5d8f38cc86ac
child 17 82331654a753
permissions -rw-r--r--
Remove api.h


/* Copyright 2009 Myhailo Danylenko
 *
 * This file is part of mcabber-templatecmd
 *
 * mcabber-templatecmd is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>. */

#include <glib.h>
#include <stdlib.h>
#include <string.h>

#include <mcabber/compl.h>
#include <mcabber/commands.h>
#include <mcabber/utils.h>
#include <mcabber/logprint.h>
#include <mcabber/modules.h>

#include "config.h"

void tcmd_init (void);
void tcmd_uninit (void);

#define DESCRIPTION ( "Templated commands\nProvides command /templatecmd (and any commands, you define with it)" )

static module_info_t info_templatecmd_dev = {
	.branch      = "dev",
	.api         = 20,
	.version     = PROJECT_VERSION,
	.description = DESCRIPTION,
	.requires    = NULL,
	.init        = tcmd_init,
	.uninit      = tcmd_uninit,
	.next        = NULL,
};

module_info_t info_templatecmd = {
	.branch      = "0.10.1",
	.api         = 1,
	.version     = PROJECT_VERSION,
	.description = DESCRIPTION,
	.requires    = NULL,
	.init        = tcmd_init,
	.uninit      = tcmd_uninit,
	.next        = &info_templatecmd_dev,
};

typedef struct {
	gchar    *name;
#ifdef MCABBER_API_HAVE_CMD_ID
	gpointer  id;
#endif
	gchar    *template;
	int       maxarg;
	gboolean  stararg;
} tcmd_t;

#ifdef MCABBER_API_HAVE_CMD_ID
static gpointer tcmd_cmid = NULL;
static gboolean tcmd_set_safe = FALSE;
#endif

static GSList *template_commands = NULL;

static void tcmd_callback (char *arg, gpointer udata)
{
	tcmd_t   *tcmd     = (tcmd_t *) udata;
	char    **args     = NULL;
	GString  *command  = g_string_new (NULL);
	char     *template = tcmd -> template;
	char     *p;

	if (tcmd -> maxarg > 0)
		args = split_arg (arg, tcmd -> maxarg, TRUE);

	for (p = template; *p; ++p) {
		if (*p != '$' || !*(p + 1) || !strchr ("*$0123456789", *(p + 1))) {
			g_string_append_c (command, *p);
			continue;
		}

		++p;

		if (*p == '*')
			g_string_append (command, arg);
		else if (*p == '$')
			g_string_append_c (command, '$');
		else {
			int argnum = atoi (p);

			if (argnum == 0)
				g_string_append (command, tcmd -> name);
			else if (args[argnum - 1])
				g_string_append (command, args[argnum - 1]);

			while (*(p + 1) && strchr ("0123456789", *(p + 1)))
				++p;
		}
	}

	{
		char *cmd = g_string_free (command, FALSE);
		process_command (cmd, 1);
		g_free (cmd);
	}

	if (args)
		free_arg_lst (args);
}

static void do_templatecmd (char *arg)
{
	if (!*arg) { // list tcmds

		GSList *tel;

		for (tel = template_commands; tel; tel = tel -> next) {
			tcmd_t *tcmd = (tcmd_t *) tel -> data;
			scr_log_print (LPRINT_NORMAL, "Templatecmd %s = %s", tcmd -> name, tcmd -> template);
		}

	} else {

		char *nend = strchr (arg, '=');

		if (!nend) { // show tcmd

			GSList *tel;

			for (tel = template_commands; tel; tel = tel -> next) {
				tcmd_t *tcmd = (tcmd_t *) tel -> data;

				if (!strcmp (arg, tcmd -> name)) {
					scr_log_print (LPRINT_NORMAL, "Templatecmd %s = %s", tcmd -> name, tcmd -> template);
					return;
				}
			}

			scr_log_print (LPRINT_NORMAL, "No template with such name.");

		} else if (nend == arg) // error

			scr_log_print (LPRINT_NORMAL, "You must specify command name.");

		else { // new/modify tcmd

			GSList *tel;
			tcmd_t *template_command = NULL;
			char   *astart           = nend + 1;
			int     len;

			for (--nend; nend > arg && *nend == ' '; --nend);
			len = nend + 1 - arg;

			for (tel = template_commands; tel; tel = tel -> next) {
				tcmd_t *tcmd = (tcmd_t *) tel -> data;

				if (!strncmp (arg, tcmd -> name, len)) {
					template_command = tcmd;
					break;
				}
			}

			for (;*astart && *astart == ' '; ++astart);

			if (!*astart) { // delete tcmd
				if (template_command) {
#ifndef MCABBER_API_HAVE_CMD_ID
					cmd_del (template_command -> name);
#else
					if (template_command -> id)
						cmd_del (template_command -> id);
#endif
					template_commands = g_slist_remove (template_commands, template_command);
					g_free (template_command -> name);
					g_free (template_command -> template);
					g_free (template_command);
				}
				return;
			}

			if (!template_command) {
				template_command = g_new (tcmd_t, 1);
				template_command -> name = g_strndup (arg, len);
			} else
				g_free (template_command -> template);

			template_command -> template = g_strdup (astart);

			{
				int      maxarg  = -1;
				gboolean stararg = FALSE;

				for (astart = strchr (astart, '$'); astart; astart = strchr (astart, '$')) {
					++astart;

					if (!*astart)
						break;

					if (strchr ("0123456789", *astart)) {
						int anum = atoi (astart);

						if (maxarg < anum)
							maxarg = anum;

					} else if (*astart == '*')
						stararg = TRUE;
				}

				template_command -> maxarg  = maxarg;
				template_command -> stararg = stararg;
			}

			template_commands = g_slist_append (template_commands, template_command);

#ifndef MCABBER_API_HAVE_CMD_ID
			cmd_add (template_command -> name, "", 0, 0, (void (*) (char *arg)) tcmd_callback, template_command);
#else
			template_command -> id = cmd_add (template_command -> name, "", 0, 0, (void (*) (char *arg)) tcmd_callback, template_command);
#endif
		}
	}
}


void tcmd_init (void)
{
#ifndef MCABBER_API_HAVE_CMD_ID
	cmd_add ("templatecmd", "", COMPL_CMD, COMPL_CMD, do_templatecmd, NULL);
#else
	tcmd_cmid = cmd_add ("templatecmd", "", COMPL_CMD, COMPL_CMD, do_templatecmd, NULL);
	tcmd_set_safe = cmd_set_safe ("templatecmd", TRUE);
#endif
}

void tcmd_uninit (void)
{
	GSList *tel;

#ifndef MCABBER_API_HAVE_CMD_ID
	cmd_del ("templatecmd");
#else
	if (tcmd_cmid)
		cmd_del (tcmd_cmid);
	if (tcmd_set_safe)
		cmd_set_safe ("templatecmd", FALSE);
#endif

	for (tel = template_commands; tel; tel = tel -> next) {
		tcmd_t *template_command = (tcmd_t *) tel -> data;
#ifndef MCABBER_API_HAVE_CMD_ID
		cmd_del (template_command -> name);
#else
		if (template_command -> id)
			cmd_del (template_command -> id);
#endif
		g_free (template_command -> name);
		g_free (template_command -> template);
		g_free (template_command);
	}

	g_slist_free (template_commands);
}

/* vim: se ts=4 sw=4: */