~emersion/mrsh

ec97ac337f6321197c3809759b75eeda97e1bdc9 — Simon Ser 3 years ago 0a3100e
shell/task/word: implement trim prefix/suffix operator for simple patterns

"Simple pattern" means it doesn't contain special pattern characters, so it
can just be handled as a raw string.
2 files changed, 50 insertions(+), 4 deletions(-)

M shell/task/word.c
M test/word.sh
M shell/task/word.c => shell/task/word.c +46 -0
@@ 238,6 238,20 @@ static int apply_parameter_cond_op(struct context *ctx,
	}
}

static char *trim_str(const char *str, const char *cut, bool suffix) {
	size_t len = strlen(str);
	size_t cut_len = strlen(cut);
	if (cut_len <= len) {
		if (!suffix && memcmp(str, cut, cut_len) == 0) {
			return strdup(str + cut_len);
		}
		if (suffix && memcmp(str + len - cut_len, cut, cut_len) == 0) {
			return strndup(str, len - cut_len);
		}
	}
	return strdup(str);
}

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


@@ 260,6 274,38 @@ static int apply_parameter_str_op(struct context *ctx,
	case MRSH_PARAM_DPERCENT: // Remove Largest Suffix Pattern
	case MRSH_PARAM_HASH: // Remove Smallest Prefix Pattern
	case MRSH_PARAM_DHASH: // Remove Largest Prefix Pattern
		if (str == NULL) {
			*result = NULL;
			return 0;
		} else if (wp->arg == NULL) {
			*result = create_word_string(str);
			return 0;
		}

		bool suffix = wp->op == MRSH_PARAM_PERCENT ||
			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);
		if (ret < 0) {
			return ret;
		}

		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);
			free(arg);
			struct mrsh_word_string *result_ws =
				mrsh_word_string_create(result_str, false);
			*result = &result_ws->word;
			return 0;
		}

		assert(false); // TODO
	default:
		assert(false);

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