handle double wide characters in str-insert
This commit is contained in:
parent
9965fe99fe
commit
585786318f
@ -150,7 +150,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
|||||||
"str-insert".to_owned(),
|
"str-insert".to_owned(),
|
||||||
Box::new(|args, _| {
|
Box::new(|args, _| {
|
||||||
max_args!(args, 3);
|
max_args!(args, 3);
|
||||||
let (mut string, q) = match arg!(args, 0, "string") {
|
let (s1, q) = match arg!(args, 0, "string") {
|
||||||
Value::Ident(i, q) => (i, q),
|
Value::Ident(i, q) => (i, q),
|
||||||
v => return Err(format!("$string: {} is not a string.", v).into()),
|
v => return Err(format!("$string: {} is not a string.", v).into()),
|
||||||
};
|
};
|
||||||
@ -176,27 +176,40 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
|||||||
QuoteKind::None => QuoteKind::None,
|
QuoteKind::None => QuoteKind::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = string.len();
|
let len = s1.len();
|
||||||
|
|
||||||
if index > Number::from(0) {
|
// Insert substring at char position, rather than byte position
|
||||||
string.insert_str(
|
let insert = |idx, s1: String, s2| {
|
||||||
|
s1.chars()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, c)| {
|
||||||
|
if i + 1 == idx {
|
||||||
|
c.to_string() + s2
|
||||||
|
} else if idx == 0 && i == 0 {
|
||||||
|
s2.to_string() + &c.to_string()
|
||||||
|
} else {
|
||||||
|
c.to_string()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
};
|
||||||
|
|
||||||
|
let string = if index > Number::from(0) {
|
||||||
|
insert(
|
||||||
index.to_integer().to_usize().unwrap().min(len + 1) - 1,
|
index.to_integer().to_usize().unwrap().min(len + 1) - 1,
|
||||||
|
s1,
|
||||||
&substr,
|
&substr,
|
||||||
);
|
)
|
||||||
} else if index == Number::from(0) {
|
} else if index == Number::from(0) {
|
||||||
string.insert_str(0, &substr);
|
insert(0, s1, &substr)
|
||||||
} else {
|
} else {
|
||||||
let idx = index.abs().to_integer().to_usize().unwrap();
|
let idx = index.abs().to_integer().to_usize().unwrap();
|
||||||
if idx > len {
|
if idx > len {
|
||||||
string.insert_str(0, &substr)
|
insert(0, s1, &substr)
|
||||||
} else {
|
} else {
|
||||||
string.insert_str(
|
insert(len - idx + 1, s1, &substr)
|
||||||
len - idx + 1,
|
|
||||||
&substr,
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Value::Ident(string, quotes))
|
Ok(Value::Ident(string, quotes))
|
||||||
}),
|
}),
|
||||||
|
@ -165,21 +165,26 @@ test!(
|
|||||||
"a {\n color: aXbc;\n}\n"
|
"a {\n color: aXbc;\n}\n"
|
||||||
);
|
);
|
||||||
error!(
|
error!(
|
||||||
float_idx,
|
str_insert_float_idx,
|
||||||
"a {\n color: str-insert(abcd, \"X\", .5);\n}\n", "Error: $index: 0.5 is not an int."
|
"a {\n color: str-insert(abcd, \"X\", .5);\n}\n", "Error: $index: 0.5 is not an int."
|
||||||
);
|
);
|
||||||
error!(
|
error!(
|
||||||
idx_with_units,
|
str_insert_idx_with_units,
|
||||||
"a {\n color: str-insert(abcd, \"X\", 5px);\n}\n",
|
"a {\n color: str-insert(abcd, \"X\", 5px);\n}\n",
|
||||||
"Error: $index: Expected 5px to have no units."
|
"Error: $index: Expected 5px to have no units."
|
||||||
);
|
);
|
||||||
test!(
|
test!(
|
||||||
idx_larger_than_string,
|
str_insert_idx_larger_than_string,
|
||||||
"a {\n color: str-insert(abcd, \"X\", 20);\n}\n",
|
"a {\n color: str-insert(abcd, \"X\", 20);\n}\n",
|
||||||
"a {\n color: abcdX;\n}\n"
|
"a {\n color: abcdX;\n}\n"
|
||||||
);
|
);
|
||||||
test!(
|
test!(
|
||||||
idx_larger_than_string_negative,
|
str_insert_idx_larger_than_string_negative,
|
||||||
"a {\n color: str-insert(abcd, \"X\", -20);\n}\n",
|
"a {\n color: str-insert(abcd, \"X\", -20);\n}\n",
|
||||||
"a {\n color: Xabcd;\n}\n"
|
"a {\n color: Xabcd;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
str_insert_double_width_char,
|
||||||
|
"a {\n color: str-insert(\"👭\", \"c\", 2);\n}\n",
|
||||||
|
"@charset \"UTF-8\";\na {\n color: \"👭c\";\n}\n"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user