diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index ffc225c68..f280228dd 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -272,15 +272,47 @@ static int handle_flag_f(wchar_t **argv, parser_t &parser, io_streams_t &streams return STATUS_CMD_OK; } else if (opts->fields_valid) { for (const wcstring &s : split_string(w.woptarg, L',')) { - int field = fish_wcstoi(wcsdup(s.c_str())); - if (field <= 0 || field == INT_MIN || errno == ERANGE) { - string_error(streams, _(L"%ls: Invalid fields value '%ls'\n"), argv[0], w.woptarg); - return STATUS_INVALID_ARGS; - } else if (errno) { - string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg); - return STATUS_INVALID_ARGS; + wcstring_list_t range = split_string(s, L'-'); + if (range.size() == 2) { + int begin = fish_wcstoi(wcsdup(range.at(0).c_str())); + if (begin <= 0 || begin == INT_MIN || errno == ERANGE) { + string_error(streams, _(L"%ls: Invalid range value for field '%ls'\n"), argv[0], + w.woptarg); + return STATUS_INVALID_ARGS; + } else if (errno) { + string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg); + return STATUS_INVALID_ARGS; + } + int end = fish_wcstoi(wcsdup(range.at(1).c_str())); + if (end <= 0 || end == INT_MIN || errno == ERANGE) { + string_error(streams, _(L"%ls: Invalid range value for field '%ls'\n"), argv[0], + w.woptarg); + return STATUS_INVALID_ARGS; + } else if (errno) { + string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg); + return STATUS_INVALID_ARGS; + } + if (begin <= end) { + for (int i = begin; i <= end; i++) { + opts->fields.push_back(i); + } + } else { + for (int i = begin; i >= end; i--) { + opts->fields.push_back(i); + } + } + } else { + int field = fish_wcstoi(wcsdup(s.c_str())); + if (field <= 0 || field == INT_MIN || errno == ERANGE) { + string_error(streams, _(L"%ls: Invalid fields value '%ls'\n"), argv[0], + w.woptarg); + return STATUS_INVALID_ARGS; + } else if (errno) { + string_error(streams, BUILTIN_ERR_NOT_NUMBER, argv[0], w.woptarg); + return STATUS_INVALID_ARGS; + } + opts->fields.push_back(field); } - opts->fields.push_back(field); } return STATUS_CMD_OK; } diff --git a/tests/checks/string.fish b/tests/checks/string.fish index d450621cb..89a8bc54d 100644 --- a/tests/checks/string.fish +++ b/tests/checks/string.fish @@ -91,13 +91,22 @@ string split "" abc string split --fields=2 "" abc # CHECK: b -string split --fields=2,3 "" abc -# CHECK: b +string split --fields=3,2 "" abc # CHECK: c +# CHECK: b string split --fields=2,9 "" abc # CHECK: b +string split --fields=1-3,5,9-7 "" 123456789 +# CHECK: 1 +# CHECK: 2 +# CHECK: 3 +# CHECK: 5 +# CHECK: 9 +# CHECK: 8 +# CHECK: 7 + seq 3 | string join ... # CHECK: 1...2...3