degesch: allow multiple commands in aliases

Separated by ;, which can be escaped as $;
This commit is contained in:
Přemysl Eric Janouch 2015-07-16 21:58:49 +02:00
parent 1b56b4ee72
commit 403dbc83ab

118
degesch.c
View File

@ -8034,59 +8034,75 @@ process_user_command
return true; return true;
} }
static char * static const char *
expand_alias_definition (const struct str *definition, const char *arguments) expand_alias_escape (const char *p, const char *arguments, struct str *output)
{ {
struct str_vector v; struct str_vector words;
str_vector_init (&v); str_vector_init (&words);
cstr_split_ignore_empty (arguments, ' ', &v); 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; struct str expanded;
str_init (&expanded); str_init (&expanded);
// TODO: eventually also support argument ranges
bool escape = false; bool escape = false;
for (const char *p = definition->str; *p; p++) for (const char *p = definition->str; *p; p++)
{ {
if (!escape) if (escape)
{ {
if (*p == '$' && p[1]) p = expand_alias_escape (p, arguments, &expanded);
escape = true; escape = false;
else
str_append_c (&expanded, *p);
continue;
} }
else if (*p == ';')
int as_number = *p - '0'; {
if (as_number > 0 && as_number <= 9 str_vector_add_owned (commands, str_steal (&expanded));
&& (size_t) as_number <= v.len) str_init (&expanded);
str_append (&expanded, v.vector[as_number - 1]); }
else if (*p == '*') else if (*p == '$' && p[1])
str_append (&expanded, arguments); escape = true;
else if (*p == '$')
str_append_c (&expanded, '$');
else else
str_append_printf (&expanded, "$%c", *p); str_append_c (&expanded, *p);
escape = false;
} }
str_vector_free (&v); str_vector_add_owned (commands, str_steal (&expanded));
return str_steal (&expanded);
} }
static char * static bool
expand_alias (struct app_context *ctx, const char *alias_name, char *input) expand_alias (struct app_context *ctx,
const char *alias_name, char *input, struct str_vector *commands)
{ {
struct config_item_ *entry = struct config_item_ *entry =
str_map_find (get_aliases_config (ctx), alias_name); str_map_find (get_aliases_config (ctx), alias_name);
if (!entry) if (!entry)
return NULL; return false;
if (config_item_type_is_string (entry->type)) if (!config_item_type_is_string (entry->type))
return expand_alias_definition (&entry->value.string, input); {
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", expand_alias_definition (&entry->value.string, input, commands);
alias_name, "alias definition is not a string"); return true;
return NULL;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -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) process_input_utf8 (struct app_context *ctx, char *input, int alias_level)
{ {
if (*input != '/' || *++input == '/') if (*input != '/' || *++input == '/')
{ {
send_message_to_current_buffer (ctx, input); send_message_to_current_buffer (ctx, input);
return; return true;
} }
char *name = cut_word (&input); char *name = cut_word (&input);
if (process_user_command (ctx, name, input)) if (process_user_command (ctx, name, input))
return; return true;
char *expanded = expand_alias (ctx, name, input); struct str_vector commands;
if (expanded) str_vector_init (&commands);
log_global_debug (ctx, "Alias expanded to \"#s\"", expanded);
if (!expanded) bool result = false;
if (!expand_alias (ctx, name, input, &commands))
log_global_error (ctx, "#s: /#s", "No such command or alias", name); log_global_error (ctx, "#s: /#s", "No such command or alias", name);
else if (alias_level != 0) else if (alias_level != 0)
log_global_error (ctx, "#s: /#s", "Aliases can't nest", name); log_global_error (ctx, "#s: /#s", "Aliases can't nest", name);
else else
process_input_utf8 (ctx, expanded, ++alias_level); result = process_alias (ctx, &commands, alias_level);
free (expanded);
str_vector_free (&commands);
return result;
} }
static void 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))) if (!(input = iconv_xstrdup (ctx->term_to_utf8, user_input, -1, NULL)))
print_error ("character conversion failed for `%s'", "user input"); print_error ("character conversion failed for `%s'", "user input");
else else
process_input_utf8 (ctx, input, 0); (void) process_input_utf8 (ctx, input, 0);
free (input); free (input);
} }