ec97ac337f6321197c3809759b75eeda97e1bdc9 — Simon Ser 2 months 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##*/}