mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 05:43:11 +00:00
builtin_string: add pad command
This commit is contained in:
parent
d8e2cac83e
commit
c8e1894c72
2 changed files with 98 additions and 4 deletions
42
doc_src/cmds/string-pad.rst
Normal file
42
doc_src/cmds/string-pad.rst
Normal file
|
@ -0,0 +1,42 @@
|
|||
string-pad - pad characters before and after string
|
||||
========================================
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
.. BEGIN SYNOPSIS
|
||||
|
||||
::
|
||||
|
||||
string pad [(-l | --left)] [(-r | --right)] [(-c | --char) CHAR] [(-n | --count) INTEGER] [(-q | --quiet)] [STRING...]
|
||||
|
||||
.. END SYNOPSIS
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
.. BEGIN DESCRIPTION
|
||||
|
||||
``string pad`` pads before and after the string specified character for each STRING. If ``-l`` or ``--left`` is given, only padded before string. Left only is the default padding. If ``-r`` or ``--right`` is given, only padded after string. The ``-c`` or ``--char`` switch causes the characters in CHAR to be padded instead of whitespace. The ``-n`` or ``--count`` integer specifies the amount of characters to be padded. The default padding count is 0. Exit status: 0 if string was padded, or 1 otherwise.
|
||||
|
||||
.. END DESCRIPTION
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
.. BEGIN EXAMPLES
|
||||
|
||||
::
|
||||
|
||||
>_ string pad -l -n 10 -c ' ' 'abc'
|
||||
abc
|
||||
|
||||
>_ string pad --right --count 5 --char=z foo bar
|
||||
foozzzzz
|
||||
barzzzzz
|
||||
|
||||
>_ string pad --left --right -n 5 --char=- foo
|
||||
-----foo-----
|
||||
|
||||
|
||||
.. END EXAMPLES
|
|
@ -135,7 +135,8 @@ class arg_iterator_t {
|
|||
// valid and get the result of parsing the command for flags.
|
||||
using options_t = struct options_t { //!OCLINT(too many fields)
|
||||
bool all_valid = false;
|
||||
bool chars_valid = false;
|
||||
bool char_to_pad_valid = false;
|
||||
bool chars_to_trim_valid = false;
|
||||
bool count_valid = false;
|
||||
bool entire_valid = false;
|
||||
bool filter_valid = false;
|
||||
|
@ -180,6 +181,8 @@ using options_t = struct options_t { //!OCLINT(too many fields)
|
|||
long start = 0;
|
||||
long end = 0;
|
||||
|
||||
wchar_t char_to_pad = ' ';
|
||||
|
||||
std::vector<int> fields;
|
||||
|
||||
const wchar_t *chars_to_trim = L" \f\n\r\t\v";
|
||||
|
@ -242,9 +245,16 @@ static int handle_flag_a(wchar_t **argv, parser_t &parser, io_streams_t &streams
|
|||
|
||||
static int handle_flag_c(wchar_t **argv, parser_t &parser, io_streams_t &streams,
|
||||
const wgetopter_t &w, options_t *opts) {
|
||||
if (opts->chars_valid) {
|
||||
if (opts->chars_to_trim_valid) {
|
||||
opts->chars_to_trim = w.woptarg;
|
||||
return STATUS_CMD_OK;
|
||||
} else if (opts->char_to_pad_valid) {
|
||||
if (wcslen(w.woptarg) != 1) {
|
||||
string_error(streams, _(L"%ls: Padding should be a character '%ls'\n"), argv[0], w.woptarg);
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
opts->char_to_pad = w.woptarg[0];
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
string_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
|
||||
return STATUS_INVALID_ARGS;
|
||||
|
@ -457,7 +467,8 @@ static int handle_flag_v(wchar_t **argv, parser_t &parser, io_streams_t &streams
|
|||
static wcstring construct_short_opts(options_t *opts) { //!OCLINT(high npath complexity)
|
||||
wcstring short_opts(L":");
|
||||
if (opts->all_valid) short_opts.append(L"a");
|
||||
if (opts->chars_valid) short_opts.append(L"c:");
|
||||
if (opts->char_to_pad_valid) short_opts.append(L"c:");
|
||||
if (opts->chars_to_trim_valid) short_opts.append(L"c:");
|
||||
if (opts->count_valid) short_opts.append(L"n:");
|
||||
if (opts->entire_valid) short_opts.append(L"e");
|
||||
if (opts->filter_valid) short_opts.append(L"f");
|
||||
|
@ -1245,6 +1256,46 @@ static int string_collect(parser_t &parser, io_streams_t &streams, int argc, wch
|
|||
return appended > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
static int string_pad(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
|
||||
options_t opts;
|
||||
opts.char_to_pad_valid = true;
|
||||
opts.count_valid = true;
|
||||
opts.left_valid = true;
|
||||
opts.right_valid = true;
|
||||
opts.quiet_valid = true;
|
||||
int optind;
|
||||
int retval = parse_opts(&opts, &optind, 0, argc, argv, parser, streams);
|
||||
if (retval != STATUS_CMD_OK) return retval;
|
||||
|
||||
// If neither left or right is specified, we pad only on the left.
|
||||
if (!opts.left && !opts.right) {
|
||||
opts.left = true;
|
||||
opts.right = false;
|
||||
}
|
||||
|
||||
size_t npad = 0;
|
||||
|
||||
arg_iterator_t aiter(argv, optind, streams);
|
||||
while (const wcstring *arg = aiter.nextstr()) {
|
||||
size_t begin = 0, end = arg->size();
|
||||
wcstring padded_arg = wcstring(*arg, 0, arg->size());
|
||||
if (opts.right) {
|
||||
padded_arg.append(opts.count, opts.char_to_pad);
|
||||
}
|
||||
if (opts.left) {
|
||||
padded_arg.insert(0, opts.count, opts.char_to_pad);
|
||||
}
|
||||
// assert(begin <= end && end <= arg->size());
|
||||
npad += arg->size() - (end - begin);
|
||||
if (!opts.quiet) {
|
||||
streams.out.append(padded_arg);
|
||||
streams.out.append(L'\n');
|
||||
}
|
||||
}
|
||||
|
||||
return npad > 0 ? STATUS_CMD_OK : STATUS_CMD_ERROR;
|
||||
}
|
||||
|
||||
// Helper function to abstract the repeat logic from string_repeat
|
||||
// returns the to_repeat string, repeated count times.
|
||||
static wcstring wcsrepeat(const wcstring &to_repeat, size_t count) {
|
||||
|
@ -1363,7 +1414,7 @@ static int string_sub(parser_t &parser, io_streams_t &streams, int argc, wchar_t
|
|||
|
||||
static int string_trim(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv) {
|
||||
options_t opts;
|
||||
opts.chars_valid = true;
|
||||
opts.chars_to_trim_valid = true;
|
||||
opts.left_valid = true;
|
||||
opts.right_valid = true;
|
||||
opts.quiet_valid = true;
|
||||
|
@ -1448,6 +1499,7 @@ string_subcommands[] = {
|
|||
{L"split", &string_split}, {L"split0", &string_split0}, {L"sub", &string_sub},
|
||||
{L"trim", &string_trim}, {L"lower", &string_lower}, {L"upper", &string_upper},
|
||||
{L"repeat", &string_repeat}, {L"unescape", &string_unescape}, {L"collect", &string_collect},
|
||||
{L"pad", &string_pad},
|
||||
{nullptr, nullptr}};
|
||||
|
||||
/// The string builtin, for manipulating strings.
|
||||
|
|
Loading…
Reference in a new issue