static struct prompt_toggle * find_prompt_toggle(struct prompt_toggle toggles[], size_t toggles_size, const char *prefix, const char *name, size_t namelen) { char prefixed[SIZEOF_STR]; int i; if (*prefix && namelen == strlen(prefix) && !string_enum_compare(prefix, name, namelen)) { name = "display"; namelen = strlen(name); } for (i = 0; i < toggles_size; i++) { struct prompt_toggle *toggle = &toggles[i]; if (namelen == strlen(toggle->name) && !string_enum_compare(toggle->name, name, namelen)) return toggle; if (enum_name_prefixed(prefixed, sizeof(prefixed), prefix, toggle->name) && namelen == strlen(prefixed) && !string_enum_compare(prefixed, name, namelen)) return toggle; } return NULL; }
static enum status_code prompt_toggle_option(struct view *view, const char *argv[], const char *prefix, struct prompt_toggle *toggle, enum view_flag *flags) { char name[SIZEOF_STR]; if (!enum_name_prefixed(name, sizeof(name), prefix, toggle->name)) return error("Failed to toggle option %s", toggle->name); *flags = toggle->flags; if (!strcmp(toggle->type, "bool")) { bool *opt = toggle->opt; *opt = !*opt; if (opt == &opt_mouse) enable_mouse(*opt); return success("set %s = %s", name, *opt ? "yes" : "no"); } else if (!strncmp(toggle->type, "enum", 4)) { const char *type = toggle->type + STRING_SIZE("enum "); enum author *opt = toggle->opt; const struct enum_map *map = find_enum_map(type); *opt = (*opt + 1) % map->size; return success("set %s = %s", name, enum_name(map->entries[*opt].name)); } else if (!strcmp(toggle->type, "int")) { const char *arg = argv[2] ? argv[2] : "1"; int diff = atoi(arg); int *opt = toggle->opt; if (!diff) diff = *arg == '-' ? -1 : 1; if (opt == &opt_diff_context && *opt < 0) *opt = -*opt; if (opt == &opt_diff_context && diff < 0) { if (!*opt) return error("Diff context cannot be less than zero"); if (*opt < -diff) diff = -*opt; } if (strstr(name, "commit-title-overflow")) { *opt = *opt ? -*opt : 50; if (*opt < 0) return success("set %s = no", name); diff = 0; } *opt += diff; return success("set %s = %d", name, *opt); } else if (!strcmp(toggle->type, "double")) { const char *arg = argv[2] ? argv[2] : "1.0"; double *opt = toggle->opt; int sign = 1; double diff; if (*arg == '-') { sign = -1; arg++; } if (parse_step(&diff, arg) != SUCCESS) diff = strtod(arg, NULL); *opt += sign * diff; return success("set %s = %.2f", name, *opt); } else if (!strcmp(toggle->type, "const char **")) { const char ***opt = toggle->opt; bool found = TRUE; int i; if (argv_size(argv) <= 2) { argv_free(*opt); (*opt)[0] = NULL; return SUCCESS; } for (i = 2; argv[i]; i++) { if (!find_arg(*opt, argv[i])) { found = FALSE; break; } } if (found) { int next, pos; for (next = 0, pos = 0; (*opt)[pos]; pos++) { const char *arg = (*opt)[pos]; if (find_arg(argv + 2, arg)) { free((void *) arg); continue; } (*opt)[next++] = arg; } (*opt)[next] = NULL; } else if (!argv_copy(opt, argv + 2)) { return ERROR_OUT_OF_MEMORY; } return SUCCESS; } else { return error("Unsupported `:toggle %s` (%s)", name, toggle->type); } }
enum status_code parse_option(struct option_info *option, const char *prefix, const char *arg) { char name[SIZEOF_STR]; if (!enum_name_prefixed(name, sizeof(name), prefix, option->name)) return error("Failed to parse option"); if (!strcmp("show-notes", name)) { bool *value = option->value; enum status_code res; if (parse_bool(option->value, arg) == SUCCESS) return SUCCESS; *value = TRUE; string_copy(opt_notes_arg, NOTES_EQ_ARG); res = parse_string(opt_notes_arg + STRING_SIZE(NOTES_EQ_ARG), arg, sizeof(opt_notes_arg) - STRING_SIZE(NOTES_EQ_ARG)); if (res == SUCCESS && !opt_notes_arg[STRING_SIZE(NOTES_EQ_ARG)]) opt_notes_arg[STRING_SIZE(NOTES_ARG)] = 0; return res; } if (!strcmp(option->type, "bool")) return parse_bool(option->value, arg); if (!strcmp(option->type, "double")) return parse_step(option->value, arg); if (!strncmp(option->type, "enum", 4)) { const char *type = option->type + STRING_SIZE("enum "); const struct enum_map *map = find_enum_map(type); return parse_enum(name, option->value, arg, map); } if (!strcmp(option->type, "int")) { if (strstr(name, "title-overflow")) { bool enabled = FALSE; int *value = option->value; /* We try to parse it as a boolean (and set the * value to 0 if fale), otherwise we parse it as * an integer and use the given value. */ if (parse_bool(&enabled, arg) == SUCCESS) { if (!enabled) { *value = 0; return SUCCESS; } arg = "50"; } } if (!strcmp(name, "line-number-interval") || !strcmp(name, "tab-size")) return parse_int(option->value, arg, 1, 1024); else if (!strcmp(name, "id-width")) return parse_int(option->value, arg, 0, SIZEOF_REV - 1); else return parse_int(option->value, arg, 0, 1024); } return error("Unhandled option: %s", name); }