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); }
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); } }
static enum view_flag prompt_toggle_option(struct view *view, const char *argv[], struct prompt_toggle *toggle, char msg[SIZEOF_STR]) { char name[SIZEOF_STR]; enum_name_copy(name, toggle->name, strlen(toggle->name)); if (!strcmp(toggle->type, "bool")) { bool *opt = toggle->opt; *opt = !*opt; string_format_size(msg, SIZEOF_STR, "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; string_format_size(msg, SIZEOF_STR, "set %s = %s", name, enum_name(map->entries[*opt])); } 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 && diff < 0) { if (!*opt) { report("Diff context cannot be less than zero"); return VIEW_NO_FLAGS; } if (*opt < -diff) diff = -*opt; } if (opt == &opt_title_overflow) { *opt = *opt ? -*opt : 50; if (*opt < 0) { string_format_size(msg, SIZEOF_STR, "set %s = no", name); return toggle->flags; } } *opt += diff; string_format_size(msg, SIZEOF_STR, "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; string_format_size(msg, SIZEOF_STR, "set %s = %.2f", name, *opt); } else if (!strcmp(toggle->type, "const char **")) { const char ***opt = toggle->opt; bool found = TRUE; int i; 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)) { report("Failed to append arguments"); return VIEW_NO_FLAGS; } } else { die("Unsupported `:toggle %s` (%s)", name, toggle->type); } return toggle->flags; }