From 403dbc83abab3441281d1b2d21b152e73284613c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Thu, 16 Jul 2015 21:58:49 +0200 Subject: [PATCH] degesch: allow multiple commands in aliases Separated by ;, which can be escaped as $; --- degesch.c | 118 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 43 deletions(-) diff --git a/degesch.c b/degesch.c index 8562946..a570733 100644 --- a/degesch.c +++ b/degesch.c @@ -8034,59 +8034,75 @@ process_user_command return true; } -static char * -expand_alias_definition (const struct str *definition, const char *arguments) +static const char * +expand_alias_escape (const char *p, const char *arguments, struct str *output) { - struct str_vector v; - str_vector_init (&v); - cstr_split_ignore_empty (arguments, ' ', &v); + struct str_vector words; + str_vector_init (&words); + cstr_split_ignore_empty (arguments, ' ', &words); + // TODO: eventually also add support for argument ranges + int as_number = *p - '0'; + if (as_number > 0 && as_number <= 9 + && (size_t) as_number <= words.len) + str_append (output, words.vector[as_number - 1]); + else if (*p == '*') + str_append (output, arguments); + else if (strchr ("$;", *p)) + str_append_c (output, *p); + else + str_append_printf (output, "$%c", *p); + + str_vector_free (&words); + return ++p; +} + +static void +expand_alias_definition (const struct str *definition, const char *arguments, + struct str_vector *commands) +{ struct str expanded; str_init (&expanded); - // TODO: eventually also support argument ranges bool escape = false; for (const char *p = definition->str; *p; p++) { - if (!escape) + if (escape) { - if (*p == '$' && p[1]) - escape = true; - else - str_append_c (&expanded, *p); - continue; + p = expand_alias_escape (p, arguments, &expanded); + escape = false; } - - int as_number = *p - '0'; - if (as_number > 0 && as_number <= 9 - && (size_t) as_number <= v.len) - str_append (&expanded, v.vector[as_number - 1]); - else if (*p == '*') - str_append (&expanded, arguments); - else if (*p == '$') - str_append_c (&expanded, '$'); + else if (*p == ';') + { + str_vector_add_owned (commands, str_steal (&expanded)); + str_init (&expanded); + } + else if (*p == '$' && p[1]) + escape = true; else - str_append_printf (&expanded, "$%c", *p); - escape = false; + str_append_c (&expanded, *p); } - str_vector_free (&v); - return str_steal (&expanded); + str_vector_add_owned (commands, str_steal (&expanded)); } -static char * -expand_alias (struct app_context *ctx, const char *alias_name, char *input) +static bool +expand_alias (struct app_context *ctx, + const char *alias_name, char *input, struct str_vector *commands) { struct config_item_ *entry = str_map_find (get_aliases_config (ctx), alias_name); if (!entry) - return NULL; + return false; - if (config_item_type_is_string (entry->type)) - return expand_alias_definition (&entry->value.string, input); + if (!config_item_type_is_string (entry->type)) + { + log_global_error (ctx, "Error executing `/%s': %s", + alias_name, "alias definition is not a string"); + return false; + } - log_global_error (ctx, "Error executing `/%s': %s", - alias_name, "alias definition is not a string"); - return NULL; + expand_alias_definition (&entry->value.string, input, commands); + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -8123,30 +8139,46 @@ send_message_to_current_buffer (struct app_context *ctx, char *message) } } -static void +static bool process_input_utf8 (struct app_context *, char *, int); + +static bool +process_alias (struct app_context *ctx, struct str_vector *commands, int level) +{ + for (size_t i = 0; i < commands->len; i++) + log_global_debug (ctx, "Alias expanded to: ###d: \"#s\"", + (int) i, commands->vector[i]); + for (size_t i = 0; i < commands->len; i++) + if (!process_input_utf8 (ctx, commands->vector[i], ++level)) + return false; + return true; +} + +static bool process_input_utf8 (struct app_context *ctx, char *input, int alias_level) { if (*input != '/' || *++input == '/') { send_message_to_current_buffer (ctx, input); - return; + return true; } char *name = cut_word (&input); if (process_user_command (ctx, name, input)) - return; + return true; - char *expanded = expand_alias (ctx, name, input); - if (expanded) - log_global_debug (ctx, "Alias expanded to \"#s\"", expanded); + struct str_vector commands; + str_vector_init (&commands); - if (!expanded) + bool result = false; + if (!expand_alias (ctx, name, input, &commands)) log_global_error (ctx, "#s: /#s", "No such command or alias", name); else if (alias_level != 0) log_global_error (ctx, "#s: /#s", "Aliases can't nest", name); else - process_input_utf8 (ctx, expanded, ++alias_level); - free (expanded); + result = process_alias (ctx, &commands, alias_level); + + str_vector_free (&commands); + return result; } static void @@ -8156,7 +8188,7 @@ process_input (struct app_context *ctx, char *user_input) if (!(input = iconv_xstrdup (ctx->term_to_utf8, user_input, -1, NULL))) print_error ("character conversion failed for `%s'", "user input"); else - process_input_utf8 (ctx, input, 0); + (void) process_input_utf8 (ctx, input, 0); free (input); }