bool argv_format(struct argv_env *argv_env, const char ***dst_argv, const char *src_argv[], bool first, bool file_filter) { struct format_var vars[] = { #define FORMAT_VAR(type, name, ifempty, initval) \ { "%(" #name ")", STRING_SIZE("%(" #name ")"), type ## _formatter, &argv_env->name, ifempty }, ARGV_ENV_INFO(FORMAT_VAR) #define FORMAT_REPO_VAR(type, name) \ { "%(repo:" #name ")", STRING_SIZE("%(repo:" #name ")"), type ## _formatter, &repo.name, "" }, REPO_INFO(FORMAT_REPO_VAR) }; struct format_context format = { vars, ARRAY_SIZE(vars), "", 0, file_filter }; int argc; argv_free(*dst_argv); for (argc = 0; src_argv[argc]; argc++) { const char *arg = src_argv[argc]; if (!strcmp(arg, "%(fileargs)")) { if (file_filter && !argv_append_array(dst_argv, opt_file_args)) break; } else if (!strcmp(arg, DIFF_ARGS)) { if (!format_append_argv(&format, dst_argv, opt_diff_options)) break; } else if (!strcmp(arg, "%(blameargs)")) { if (!format_append_argv(&format, dst_argv, opt_blame_options)) break; } else if (!strcmp(arg, "%(logargs)")) { if (!format_append_argv(&format, dst_argv, opt_log_options)) break; } else if (!strcmp(arg, "%(mainargs)")) { if (!format_append_argv(&format, dst_argv, opt_main_options)) break; } else if (!strcmp(arg, "%(cmdlineargs)")) { if (!format_append_argv(&format, dst_argv, opt_cmdline_args)) break; } else if (!strcmp(arg, "%(revargs)") || (first && !strcmp(arg, "%(commit)"))) { if (!argv_append_array(dst_argv, opt_rev_args)) break; } else if (!format_append_arg(&format, dst_argv, arg)) { break; } } return src_argv[argc] == NULL; }
static char * readline_variable_generator(const char *text, int state) { static const char *vars[] = { #define FORMAT_VAR(name, ifempty, initval) "%(" #name ")" ARGV_ENV_INFO(FORMAT_VAR), #undef FORMAT_VAR NULL }; static int index, len; const char *name; char *variable = NULL; /* No match */ /* If it is a new word to complete, initialize */ if (!state) { index = 0; len = strlen(text); } /* Return the next name which partially matches */ while ((name = vars[index])) { index++; /* Complete or format a variable */ if (strncmp(name, text, len) == 0) { if (strlen(name) > len) variable = strdup(name); else variable = argv_format_arg(&argv_env, text); break; } } return variable; }
const char *value; const char *value_if_empty; }; struct format_context { struct format_var *vars; size_t vars_size; char buf[SIZEOF_STR]; size_t bufpos; bool file_filter; }; #define ARGV_ENV_INIT(name, ifempty, initval) initval struct argv_env argv_env = { ARGV_ENV_INFO(ARGV_ENV_INIT) }; static bool format_expand_arg(struct format_context *format, const char *name, const char *end) { struct format_var *vars = format->vars; int i; if (!prefixcmp(name, "%(prompt")) { const char *prompt = "Command argument: "; char msgbuf[SIZEOF_STR]; const char *value; const char *msgstart = name + STRING_SIZE("%(prompt"); int msglen = end - msgstart - 1;