~emersion/mrsh

b51626ffc33dc159b9a535b86a859a99f8eea472 — Simon Ser 10 months ago ec97ac3
shell/task/word: add prefix/suffix trim with full pattern support
2 files changed, 56 insertions(+), 11 deletions(-)

M shell/task/word.c
M test/word.sh
M shell/task/word.c => shell/task/word.c +52 -7
@@ 1,6 1,7 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <errno.h>
#include <fnmatch.h>
#include <mrsh/buffer.h>
#include <mrsh/parser.h>
#include <stdio.h>


@@ 252,6 253,47 @@ static char *trim_str(const char *str, const char *cut, bool suffix) {
	return strdup(str);
}

static char *trim_pattern(const char *str, const char *pattern, bool suffix,
		bool largest) {
	size_t len = strlen(str);
	ssize_t begin, end, delta;
	if ((!suffix && !largest) || (suffix && largest)) {
		begin = 0;
		end = len;
		delta = 1;
	} else {
		begin = len - 1;
		end = -1;
		delta = -1;
	}

	char *buf = strdup(str);
	for (ssize_t i = begin; i != end; i += delta) {
		char ch = buf[i];
		buf[i] = '\0';

		const char *match, *trimmed;
		if (!suffix) {
			match = buf;
			trimmed = str + i;
		} else {
			match = str + i;
			trimmed = buf;
		}

		if (fnmatch(pattern, match, 0) == 0) {
			char *result = strdup(trimmed);
			free(buf);
			return result;
		}

		buf[i] = ch;
	}
	free(buf);

	return strdup(str);
}

static int apply_parameter_str_op(struct context *ctx,
		struct mrsh_word_parameter *wp, const char *str,
		struct mrsh_word **result) {


@@ 286,7 328,6 @@ static int apply_parameter_str_op(struct context *ctx,
			wp->op == MRSH_PARAM_DPERCENT;
		bool largest = wp->op == MRSH_PARAM_DPERCENT ||
			wp->op == MRSH_PARAM_DHASH;
		(void)largest;

		struct mrsh_word *pattern = mrsh_word_copy(wp->arg);
		int ret = run_word(ctx, &pattern);


@@ 294,19 335,23 @@ static int apply_parameter_str_op(struct context *ctx,
			return ret;
		}

		char *result_str;
		char *pattern_str = word_to_pattern(pattern);
		if (pattern_str == NULL) {
			char *arg = mrsh_word_str(pattern);
			mrsh_word_destroy(pattern);
			char *result_str = trim_str(str, arg, suffix);
			result_str = trim_str(str, arg, suffix);
			free(arg);
			struct mrsh_word_string *result_ws =
				mrsh_word_string_create(result_str, false);
			*result = &result_ws->word;
			return 0;
		} else {
			mrsh_word_destroy(pattern);
			result_str = trim_pattern(str, pattern_str, suffix, largest);
			free(pattern_str);
		}

		assert(false); // TODO
		struct mrsh_word_string *result_ws =
			mrsh_word_string_create(result_str, false);
		*result = &result_ws->word;
		return 0;
	default:
		assert(false);
	}

M test/word.sh => test/word.sh +4 -4
@@ 59,14 59,14 @@ echo ${#posix}
x=file.c
echo ${x%.c}.o
# ${parameter%%word}
#x=posix/src/std
#echo ${x%%/*}
x=posix/src/std
echo ${x%%/*}
# ${parameter#word}
x=$HOME/src/cmd
echo ${x#$HOME}
# ${parameter##word}
#x=/one/two/three
#echo ${x##*/}
x=/one/two/three
echo ${x##*/}

echo ""
echo "Command Substitution"