From 9b51188920069a4dbfabf8bf880e695a7613c9a2 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Eli=C3=A1n=20Hanisch?= <lambdae2@gmail.com>
Date: Wed, 16 Sep 2009 10:55:12 -0300
Subject: [PATCH] adds more expansions for aliases

$n- $-n $n-m for specifying a range of arguments
$~ for last argument
---
 src/plugins/alias/alias.c |  162 +++++++++++++++++++++++++++++++++------------
 1 files changed, 120 insertions(+), 42 deletions(-)

diff --git a/src/plugins/alias/alias.c b/src/plugins/alias/alias.c
index 48897c9..72fc750 100644
--- a/src/plugins/alias/alias.c
+++ b/src/plugins/alias/alias.c
@@ -117,15 +117,49 @@ alias_add_word (char **alias, int *length, const char *word)
 }
 
 /*
- * alias_replace_args: replace arguments ($1, $2, .. or $*) in alias arguments
+ * alias_add_range: add word in range specified by start, end
+ *                  and increment length
+ */
+
+void
+alias_add_range (char **res, int *length, const char *start, const char *end)
+{
+    char *word;
+
+    word = weechat_strndup (start, end - start);
+    if (word)
+    {
+        alias_add_word (res, length, word);
+        free (word);
+    }
+}
+
+/*
+ * is_number: checks if char is a number between '1'..'9'
+ */
+
+int
+is_number (const char number)
+{
+    if (number >= '1' && number <= '9')
+        return 1;
+    else
+        return 0;
+}
+
+/*
+ * alias_replace_args: replace arguments in alias
+ *                     valid arguments are:
+ *                     $n $-m $n- $n-m $* $~ with n,m in (1..9)
  */
 
 char *
 alias_replace_args (const char *alias_args, const char *user_args)
 {
-    char **argv, *res, *word;
+    char **argv, *res;
     const char *start, *pos;
-    int argc, length_res, args_count;
+    int argc, length_res, args_count, offset;
+    int i, n, m;
     
     argv = weechat_string_split (user_args, " ", 0, 0, &argc);
     
@@ -134,19 +168,14 @@ alias_replace_args (const char *alias_args, const char *user_args)
     args_count = 0;
     start = alias_args;
     pos = start;
+    offset = 0;
     while (pos && pos[0])
     {
         if ((pos[0] == '\\') && (pos[1] == '$'))
         {
-            word = weechat_strndup (start, pos - start);
-            if (word)
-            {
-                alias_add_word (&res, &length_res, word);
-                free (word);
-            }
+            offset = 2;
+            alias_add_range (&res, &length_res, start, pos);
             alias_add_word (&res, &length_res, "$");
-            start = pos + 2;
-            pos = start;
         }
         else
         {
@@ -154,46 +183,90 @@ alias_replace_args (const char *alias_args, const char *user_args)
             {
                 if (pos[1] == '*')
                 {
+                    /* replace with all arguments */
+                    args_count++;
+                    offset = 2;
+                    if (start < pos)
+                        alias_add_range (&res, &length_res, start, pos);
+                    alias_add_word (&res, &length_res, user_args);
+                }
+                else if (pos[1] == '~')
+                {
+                    /* replace with last argument */
+                    args_count++;
+                    offset = 2;
+                    if (start < pos)
+                        alias_add_range (&res, &length_res, start, pos);
+                    if (argc > 0)
+                        alias_add_word (&res, &length_res, argv[argc - 1]);
+                }
+                else if (pos[1] == '-' && is_number (pos[2]))
+                {
+                    /* replace with the first to mth arguments */
                     args_count++;
-                    if (pos > start)
+                    offset = 3;
+                    if (start < pos)
+                        alias_add_range (&res, &length_res, start, pos);
+                    if (pos[2] - '1' < argc)
+                        m = pos[2] - '0';
+                    else
+                        m = argc;
+                    for (i = 0; i < m; i++)
                     {
-                        word = weechat_strndup (start, pos - start);
-                        if (word)
-                        {
-                            alias_add_word (&res, &length_res, word);
-                            free (word);
-                        }
+                        if (i)
+                            alias_add_word (&res, &length_res, " ");
+                        alias_add_word (&res, &length_res, argv[i]);
                     }
-                    alias_add_word (&res, &length_res, user_args);
-                    start = pos + 2;
-                    pos = start;
                 }
-                else
+                else if (is_number (pos[1]))
                 {
-                    if ((pos[1] >= '1') && (pos[1] <= '9'))
+                    args_count++;
+                    n = pos[1] - '1';
+                    if (start < pos)
+                        alias_add_range (&res, &length_res, start, pos);
+                    if (pos[2] != '-')
                     {
-                        args_count++;
-                        if (pos > start)
+                        /* replace with the nth argument */
+                        offset = 2;
+                        if (n < argc)
+                            alias_add_word (&res, &length_res, argv[n]);
+                    }
+                    else
+                    {
+                        if (is_number (pos[3]))
+                        {
+                            /* replace with the nth to mth arguments */
+                            offset = 4;
+                            if (pos[3] - '1' < argc)
+                                m = pos[3] - '0';
+                            else
+                                m = argc;
+                        }
+                        else
                         {
-                            word = weechat_strndup (start, pos - start);
-                            if (word)
+                            /* replace with the nth to last arguments */
+                            offset = 3;
+                            m = argc;
+                        }
+                        if (n < argc)
+                            for (i = n; i < m; i++)
                             {
-                                alias_add_word (&res, &length_res, word);
-                                free (word);
+                                if (i != n)
+                                    alias_add_word (&res, &length_res, " ");
+                                alias_add_word (&res, &length_res, argv[i]);
                             }
-                        }
-                        if (pos[1] - '1' < argc)
-                            alias_add_word (&res, &length_res, argv[pos[1] - '1']);
-                        start = pos + 2;
-                        pos = start;
                     }
-                    else
-                        pos++;
                 }
             }
-            else
-                pos++;
         }
+        if (offset)
+        {
+            pos += offset;
+            start = pos;
+            offset = 0;
+        }
+        else
+            pos++;
     }
     
     if (start < pos)
@@ -906,10 +979,15 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
                              " arguments: arguments for command\n\n"
                              "Without argument, this command lists all "
                              "defined alias.\n\n"
-                             "Note: in command, special variables "
-                             "$1, $2,..,$9 are replaced by arguments given "
-                             "by user, and $* is replaced by all arguments.\n"
-                             "Variables $nick, $channel and $server are "
+                             "Whenever an alias is called, the following special variables are\n"
+                             "replaced by arguments given by user.\n"
+                             "   $n : the 'n' argument (counting from 1, up to 9).\n"
+                             "  $-m : all arguments up to 'm'.\n"
+                             "  $n- : all arguments from 'n'.\n"
+                             " $n-m : all arguments from 'n' through 'm'.\n"
+                             "   $* : all arguments.\n"
+                             "   $~ : last argument.\n"
+                             "$nick, $channel and $server are "
                              "replaced by current nick/channel/server."),
                           "%(alias) %(commands)",
                           &alias_command_cb, NULL);
-- 
1.6.0.4

