mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-15 23:22:53 +08:00
Add sort --unique
This commit is contained in:
parent
54778f65f8
commit
c88f648cdf
@ -21,7 +21,7 @@ Synopsis
|
||||
path resolve GENERAL_OPTIONS [PATH...]
|
||||
path change-extension GENERAL_OPTIONS EXTENSION [PATH...]
|
||||
path sort GENERAL_OPTIONS [(-v | --invert)] \
|
||||
[--what=basename|dirname|path] [([PATH...]
|
||||
[-u | --unique] [--what=basename|dirname|path] [([PATH...]
|
||||
|
||||
GENERAL_OPTIONS := [(-z | --null-in)] [(-Z | --null-out)] [(-q | --quiet)]
|
||||
|
||||
@ -351,6 +351,8 @@ With ``--invert`` or ``-v`` the sort is reversed.
|
||||
|
||||
With ``--what=`` only the given path of the path is compared, e.g. ``--what=dirname`` causes only the dirname to be compared, ``--what=basename`` only the basename and ``--what=path`` causes the entire path to be compared (this is the default).
|
||||
|
||||
With ``--unique`` or ``-u`` the sort is deduplicated, meaning only the first of a run that have the same key is kept. So if you are sorting by basename, then only the first of each basename is used.
|
||||
|
||||
The sort used is stable, so sorting first by basename and then by dirname works and causes the files to be grouped according to directory.
|
||||
|
||||
It currently returns 0 if it was given any paths.
|
||||
@ -368,6 +370,10 @@ Examples
|
||||
10-foo
|
||||
2-bar
|
||||
|
||||
>_ path sort --unique --what=basename $fish_function_path/*.fish
|
||||
# prints a list of all function files fish would use, sorted by name.
|
||||
|
||||
|
||||
Combining ``path``
|
||||
-------------------
|
||||
|
||||
|
@ -157,6 +157,8 @@ struct options_t { //!OCLINT(too many fields)
|
||||
bool type_valid = false;
|
||||
bool invert_valid = false;
|
||||
bool what_valid = false;
|
||||
bool unique_valid = false;
|
||||
bool unique = false;
|
||||
bool have_what = false;
|
||||
const wchar_t *what = nullptr;
|
||||
|
||||
@ -348,6 +350,16 @@ static int handle_flag_v(const wchar_t **argv, parser_t &parser, io_streams_t &s
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
static int handle_flag_u(const wchar_t **argv, parser_t &parser, io_streams_t &streams,
|
||||
const wgetopter_t &w, options_t *opts) {
|
||||
if (opts->unique_valid) {
|
||||
opts->unique = true;
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
path_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
static int handle_flag_what(const wchar_t **argv, parser_t &parser, io_streams_t &streams,
|
||||
const wgetopter_t &w, options_t *opts) {
|
||||
UNUSED(argv);
|
||||
@ -373,6 +385,7 @@ static wcstring construct_short_opts(options_t *opts) { //!OCLINT(high npath co
|
||||
short_opts.append(L"fld");
|
||||
}
|
||||
if (opts->invert_valid) short_opts.append(L"v");
|
||||
if (opts->unique_valid) short_opts.append(L"u");
|
||||
return short_opts;
|
||||
}
|
||||
|
||||
@ -386,6 +399,7 @@ static const struct woption long_options[] = {
|
||||
{L"perm", required_argument, nullptr, 'p'},
|
||||
{L"type", required_argument, nullptr, 't'},
|
||||
{L"invert", required_argument, nullptr, 't'},
|
||||
{L"unique", no_argument, nullptr, 'u'},
|
||||
{L"what", required_argument, nullptr, 1},
|
||||
{}};
|
||||
|
||||
@ -396,7 +410,8 @@ static const std::unordered_map<char, decltype(*handle_flag_q)> flag_to_function
|
||||
{'r', handle_flag_r}, {'w', handle_flag_w},
|
||||
{'x', handle_flag_x}, {'f', handle_flag_f},
|
||||
{'l', handle_flag_l}, {'d', handle_flag_d},
|
||||
{1, handle_flag_what},
|
||||
{'l', handle_flag_l}, {'d', handle_flag_d},
|
||||
{'u', handle_flag_u}, {1, handle_flag_what},
|
||||
};
|
||||
|
||||
/// Parse the arguments for flags recognized by a specific string subcommand.
|
||||
@ -700,6 +715,7 @@ static int path_sort(parser_t &parser, io_streams_t &streams, int argc, const wc
|
||||
options_t opts;
|
||||
opts.invert_valid = true;
|
||||
opts.what_valid = true;
|
||||
opts.unique_valid = true;
|
||||
int optind;
|
||||
int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
|
||||
if (retval != STATUS_CMD_OK) return retval;
|
||||
@ -745,6 +761,13 @@ static int path_sort(parser_t &parser, io_streams_t &streams, int argc, const wc
|
||||
else
|
||||
return (wcsfilecmp_glob(funced[a].c_str(), funced[b].c_str()) > 0);
|
||||
});
|
||||
if (opts.unique) {
|
||||
list.erase(std::unique(list.begin(), list.end(),
|
||||
[&](const wcstring &a, const wcstring &b) {
|
||||
return funced[a] == funced[b];
|
||||
}),
|
||||
list.end());
|
||||
}
|
||||
} else {
|
||||
// Without --what, we just sort by the entire path,
|
||||
// so we have no need to transform and such.
|
||||
@ -755,6 +778,9 @@ static int path_sort(parser_t &parser, io_streams_t &streams, int argc, const wc
|
||||
else
|
||||
return (wcsfilecmp_glob(a.c_str(), b.c_str()) > 0);
|
||||
});
|
||||
if (opts.unique) {
|
||||
list.erase(std::unique(list.begin(), list.end()), list.end());
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &entry : list) {
|
||||
|
@ -155,3 +155,16 @@ path sort --what=basename {def,abc}/{456,123,789,abc,def,0} | path sort --what=d
|
||||
# CHECK: abc/789
|
||||
# CHECK: abc/abc
|
||||
# CHECK: abc/def
|
||||
|
||||
path sort --unique --what=basename {def,abc}/{456,123,789} def/{abc,def,0} abc/{foo,bar,baz}
|
||||
# CHECK: def/0
|
||||
# CHECK: def/123
|
||||
# CHECK: def/456
|
||||
# CHECK: def/789
|
||||
# CHECK: def/abc
|
||||
# CHECK: abc/bar
|
||||
# CHECK: abc/baz
|
||||
# CHECK: def/def
|
||||
# CHECK: abc/foo
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user