mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 20:33:08 +00:00
parent
5e94650645
commit
f6c9bfc0e8
4 changed files with 164 additions and 32 deletions
|
@ -9,6 +9,7 @@
|
|||
- Added completions for:
|
||||
-
|
||||
- Improved completions for `killall` (#4052), `ln` (#4090) and `zypper` (#4079).
|
||||
- Implemented `string lower` and `string upper` (#4080).
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -2,21 +2,23 @@
|
|||
|
||||
\subsection string-synopsis Synopsis
|
||||
\fish{synopsis}
|
||||
string length [(-q | --quiet)] [STRING...]
|
||||
string sub [(-s | --start) START] [(-l | --length) LENGTH] [(-q | --quiet)]
|
||||
[STRING...]
|
||||
string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)] SEP
|
||||
[STRING...]
|
||||
string join [(-q | --quiet)] SEP [STRING...]
|
||||
string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
|
||||
[(-q | --quiet)] [STRING...]
|
||||
string escape [(-n | --no-quoted)] [STRING...]
|
||||
string join [(-q | --quiet)] SEP [STRING...]
|
||||
string length [(-q | --quiet)] [STRING...]
|
||||
string lower [(-q | --quiet)] [STRING...]
|
||||
string match [(-a | --all)] [((-e | --entire)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
[(-n | --index)] [(-q | --quiet)] [(-v | --invert)] PATTERN [STRING...]
|
||||
string replace [(-a | --all)] [(-f | --filter)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
[(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
|
||||
string repeat [(-n | --count)] [(-m | --max)] [(-N | --no-newline)]
|
||||
[(-q | --quiet)] [STRING...]
|
||||
string replace [(-a | --all)] [(-f | --filter)] [(-i | --ignore-case)] [(-r | --regex)]
|
||||
[(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
|
||||
string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)] SEP
|
||||
[STRING...]
|
||||
string sub [(-s | --start) START] [(-l | --length) LENGTH] [(-q | --quiet)]
|
||||
[STRING...]
|
||||
string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
|
||||
[(-q | --quiet)] [STRING...]
|
||||
string upper [(-q | --quiet)] [STRING...]
|
||||
\endfish
|
||||
|
||||
|
||||
|
@ -32,29 +34,21 @@ Most subcommands accept a `-q` or `--quiet` switch, which suppresses the usual o
|
|||
|
||||
The following subcommands are available.
|
||||
|
||||
\subsection string-length "length" subcommand
|
||||
\subsection string-escape "escape" subcommand
|
||||
|
||||
`string length` reports the length of each string argument in characters. Exit status: 0 if at least one non-empty STRING was given, or 1 otherwise.
|
||||
|
||||
\subsection string-sub "sub" subcommand
|
||||
|
||||
`string sub` prints a substring of each string argument. The start of the substring can be specified with `-s` or `--start` followed by a 1-based index value. Positive index values are relative to the start of the string and negative index values are relative to the end of the string. The default start value is 1. The length of the substring can be specified with `-l` or `--length`. If the length is not specified, the substring continues to the end of each STRING. Exit status: 0 if at least one substring operation was performed, 1 otherwise.
|
||||
|
||||
\subsection string-split "split" subcommand
|
||||
|
||||
`string split` splits each STRING on the separator SEP, which can be an empty string. If `-m` or `--max` is specified, at most MAX splits are done on each STRING. If `-r` or `--right` is given, splitting is performed right-to-left. This is useful in combination with `-m` or `--max`. Exit status: 0 if at least one split was performed, or 1 otherwise.
|
||||
`string escape` escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quoted` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
|
||||
|
||||
\subsection string-join "join" subcommand
|
||||
|
||||
`string join` joins its STRING arguments into a single string separated by SEP, which can be an empty string. Exit status: 0 if at least one join was performed, or 1 otherwise.
|
||||
|
||||
\subsection string-trim "trim" subcommand
|
||||
\subsection string-length "length" subcommand
|
||||
|
||||
`string trim` removes leading and trailing whitespace from each STRING. If `-l` or `--left` is given, only leading whitespace is removed. If `-r` or `--right` is given, only trailing whitespace is trimmed. The `-c` or `--chars` switch causes the characters in CHARS to be removed instead of whitespace. Exit status: 0 if at least one character was trimmed, or 1 otherwise.
|
||||
`string length` reports the length of each string argument in characters. Exit status: 0 if at least one non-empty STRING was given, or 1 otherwise.
|
||||
|
||||
\subsection string-escape "escape" subcommand
|
||||
\subsection string-lower "lower" subcommand
|
||||
|
||||
`string escape` escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quoted` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
|
||||
`string lower` converts each string argument to lowercase. Exit status: 0 if at least one string was converted to lowercase, else 1. This means that in conjunction with the `-q` flag you can readily test whether a string is already lowercase.
|
||||
|
||||
\subsection string-match "match" subcommand
|
||||
|
||||
|
@ -72,6 +66,10 @@ If `--invert` or `-v` is used the selected lines will be only those which do not
|
|||
|
||||
Exit status: 0 if at least one match was found, or 1 otherwise.
|
||||
|
||||
\subsection string-repeat "repeat" subcommand
|
||||
|
||||
`string repeat` repeats the STRING `-n` or `--count` times. The `-m` or `--max` option will limit the number of outputed char (excluding the newline). This option can be used by itself or in conjuction with `--count`. If both `--count` and `--max` are present, max char will be outputed unless the final repeated string size is less than max, in that case, the string will repeat until count has been reached. Both `--count` and `--max` will accept a number greater than or equal to zero, in the case of zero, nothing will be outputed. If `-N` or `--no-newline` is given, the output won't contain a newline character at the end. Exit status: 0 if yielded string is not empty, 1 otherwise.
|
||||
|
||||
\subsection string-replace "replace" subcommand
|
||||
|
||||
`string replace` is similar to `string match` but replaces non-overlapping matching substrings with a replacement string and prints the result. By default, PATTERN is treated as a literal substring to be matched.
|
||||
|
@ -82,9 +80,21 @@ If you specify the `-f` or `--filter` flag then each input string is printed onl
|
|||
|
||||
Exit status: 0 if at least one replacement was performed, or 1 otherwise.
|
||||
|
||||
\subsection string-repeat "repeat" subcommand
|
||||
\subsection string-split "split" subcommand
|
||||
|
||||
`string repeat` repeats the STRING `-n` or `--count` times. The `-m` or `--max` option will limit the number of outputed char (excluding the newline). This option can be used by itself or in conjuction with `--count`. If both `--count` and `--max` are present, max char will be outputed unless the final repeated string size is less than max, in that case, the string will repeat until count has been reached. Both `--count` and `--max` will accept a number greater than or equal to zero, in the case of zero, nothing will be outputed. If `-N` or `--no-newline` is given, the output won't contain a newline character at the end. Exit status: 0 if yielded string is not empty, 1 otherwise.
|
||||
`string split` splits each STRING on the separator SEP, which can be an empty string. If `-m` or `--max` is specified, at most MAX splits are done on each STRING. If `-r` or `--right` is given, splitting is performed right-to-left. This is useful in combination with `-m` or `--max`. Exit status: 0 if at least one split was performed, or 1 otherwise.
|
||||
|
||||
\subsection string-sub "sub" subcommand
|
||||
|
||||
`string sub` prints a substring of each string argument. The start of the substring can be specified with `-s` or `--start` followed by a 1-based index value. Positive index values are relative to the start of the string and negative index values are relative to the end of the string. The default start value is 1. The length of the substring can be specified with `-l` or `--length`. If the length is not specified, the substring continues to the end of each STRING. Exit status: 0 if at least one substring operation was performed, 1 otherwise.
|
||||
|
||||
\subsection string-trim "trim" subcommand
|
||||
|
||||
`string trim` removes leading and trailing whitespace from each STRING. If `-l` or `--left` is given, only leading whitespace is removed. If `-r` or `--right` is given, only trailing whitespace is trimmed. The `-c` or `--chars` switch causes the characters in CHARS to be removed instead of whitespace. Exit status: 0 if at least one character was trimmed, or 1 otherwise.
|
||||
|
||||
\subsection string-upper "upper" subcommand
|
||||
|
||||
`string upper` converts each string argument to uppercase. Exit status: 0 if at least one string was converted to uppercase, else 1. This means that in conjunction with the `-q` flag you can readily test whether a string is already uppercase.
|
||||
|
||||
\subsection regular-expressions Regular Expressions
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ static const wchar_t *string_get_arg_stdin(wcstring *storage, const io_streams_t
|
|||
}
|
||||
|
||||
static const wchar_t *string_get_arg_argv(int *argidx, wchar_t **argv) {
|
||||
return argv && argv[*argidx] ? argv[(*argidx)++] : 0;
|
||||
return argv && argv[*argidx] ? argv[(*argidx)++] : NULL;
|
||||
}
|
||||
|
||||
static const wchar_t *string_get_arg(int *argidx, wchar_t **argv, wcstring *storage,
|
||||
|
@ -1241,17 +1241,111 @@ static int string_trim(parser_t &parser, io_streams_t &streams, int argc, wchar_
|
|||
return ntrim > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
static int string_lower(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
|
||||
bool quiet = false;
|
||||
|
||||
static const wchar_t *short_options = L"q";
|
||||
static const struct woption long_options[] = {{L"quiet", no_argument, NULL, 'q'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (opt) { //!OCLINT(too few branches)
|
||||
case L'q': {
|
||||
quiet = true;
|
||||
break;
|
||||
}
|
||||
case L'?': {
|
||||
string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
default: {
|
||||
DIE("unexpected retval from wgetopt_long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = w.woptind;
|
||||
if (string_args_from_stdin(streams) && argc > i) {
|
||||
string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
int n_transformed = 0;
|
||||
wcstring storage;
|
||||
while (const wchar_t *arg = string_get_arg(&i, argv, &storage, streams)) {
|
||||
wcstring transformed(arg);
|
||||
std::transform(transformed.begin(), transformed.end(), transformed.begin(), std::towlower);
|
||||
if (wcscmp(transformed.c_str(), arg)) n_transformed++;
|
||||
if (!quiet) {
|
||||
streams.out.append(transformed);
|
||||
streams.out.append(L'\n');
|
||||
}
|
||||
}
|
||||
|
||||
return n_transformed > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
static int string_upper(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
|
||||
bool quiet = false;
|
||||
|
||||
static const wchar_t *short_options = L"q";
|
||||
static const struct woption long_options[] = {{L"quiet", no_argument, NULL, 'q'},
|
||||
{NULL, 0, NULL, 0}};
|
||||
|
||||
int opt;
|
||||
wgetopter_t w;
|
||||
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
|
||||
switch (opt) { //!OCLINT(too few branches)
|
||||
case L'q': {
|
||||
quiet = true;
|
||||
break;
|
||||
}
|
||||
case L'?': {
|
||||
string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
default: {
|
||||
DIE("unexpected retval from wgetopt_long");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = w.woptind;
|
||||
if (string_args_from_stdin(streams) && argc > i) {
|
||||
string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
int n_transformed = 0;
|
||||
wcstring storage;
|
||||
while (const wchar_t *arg = string_get_arg(&i, argv, &storage, streams)) {
|
||||
wcstring transformed(arg);
|
||||
std::transform(transformed.begin(), transformed.end(), transformed.begin(), std::towupper);
|
||||
if (wcscmp(transformed.c_str(), arg)) n_transformed++;
|
||||
if (!quiet) {
|
||||
streams.out.append(transformed);
|
||||
streams.out.append(L'\n');
|
||||
}
|
||||
}
|
||||
|
||||
return n_transformed > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
static const struct string_subcommand {
|
||||
const wchar_t *name;
|
||||
int (*handler)(parser_t &, io_streams_t &, int argc, //!OCLINT(unused param)
|
||||
wchar_t **argv); //!OCLINT(unused param)
|
||||
}
|
||||
|
||||
string_subcommands[] = {{L"escape", &string_escape}, {L"join", &string_join},
|
||||
{L"length", &string_length}, {L"match", &string_match},
|
||||
{L"replace", &string_replace}, {L"split", &string_split},
|
||||
{L"sub", &string_sub}, {L"trim", &string_trim},
|
||||
{L"repeat", &string_repeat}, {0, 0}};
|
||||
string_subcommands[] = {
|
||||
{L"escape", &string_escape}, {L"join", &string_join}, {L"length", &string_length},
|
||||
{L"match", &string_match}, {L"replace", &string_replace}, {L"split", &string_split},
|
||||
{L"sub", &string_sub}, {L"trim", &string_trim}, {L"lower", &string_lower},
|
||||
{L"upper", &string_upper}, {L"repeat", &string_repeat}, {NULL, NULL}};
|
||||
|
||||
/// The string builtin, for manipulating strings.
|
||||
int builtin_string(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||
|
|
|
@ -324,4 +324,31 @@ echo '# string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabx
|
|||
string match -r "a*b([xy]+)" abc abxc bye aaabyz kaabxz abbxy abcx caabxyxz
|
||||
or echo exit 1
|
||||
|
||||
# Test `string lower` and `string upper`.
|
||||
set x (string lower abc DEF gHi)
|
||||
or echo string lower exit 1
|
||||
test $x[1] = 'abc' -a $x[2] = 'def' -a $x[3] = 'ghi'
|
||||
or echo strings not converted to lowercase
|
||||
|
||||
set x (echo abc DEF gHi | string lower)
|
||||
or echo string lower exit 1
|
||||
test $x[1] = 'abc def ghi'
|
||||
or echo strings not converted to lowercase
|
||||
|
||||
string lower -q abc
|
||||
and echo lowercasing a lowercase string did not fail as expected
|
||||
|
||||
set x (string upper abc DEF gHi)
|
||||
or echo string upper exit 1
|
||||
test $x[1] = 'ABC' -a $x[2] = 'DEF' -a $x[3] = 'GHI'
|
||||
or echo strings not converted to uppercase
|
||||
|
||||
set x (echo abc DEF gHi | string upper)
|
||||
or echo string upper exit 1
|
||||
test $x[1] = 'ABC DEF GHI'
|
||||
or echo strings not converted to uppercase
|
||||
|
||||
string upper -q ABC DEF
|
||||
and echo uppercasing a uppercase string did not fail as expected
|
||||
|
||||
exit 0
|
||||
|
|
Loading…
Reference in a new issue