ok/jj
1
0
Fork 0
forked from mirrors/jj

templater: add string.len() and list.len() methods

This commit is contained in:
Yuya Nishihara 2024-02-29 13:17:04 +09:00
parent 0656409904
commit 82b3017fda
3 changed files with 32 additions and 5 deletions

View file

@ -488,6 +488,11 @@ fn builtin_string_methods<'a, L: TemplateLanguage<'a>>() -> TemplateBuildMethodF
// Not using maplit::hashmap!{} or custom declarative macro here because
// code completion inside macro is quite restricted.
let mut map = TemplateBuildMethodFnMap::<L, String>::new();
map.insert("len", |language, _build_ctx, self_property, function| {
template_parser::expect_no_arguments(function)?;
let out_property = TemplateFunction::new(self_property, |s| Ok(s.len().try_into()?));
Ok(language.wrap_integer(out_property))
});
map.insert(
"contains",
|language, build_ctx, self_property, function| {
@ -762,6 +767,12 @@ where
O: Template<()> + Clone + 'a,
{
let property = match function.name {
"len" => {
template_parser::expect_no_arguments(function)?;
let out_property =
TemplateFunction::new(self_property, |items| Ok(items.len().try_into()?));
language.wrap_integer(out_property)
}
"join" => {
let [separator_node] = template_parser::expect_exact_arguments(function)?;
let separator = expect_template_expression(language, build_ctx, separator_node)?;
@ -789,6 +800,12 @@ where
O: Clone + 'a,
{
let property = match function.name {
"len" => {
template_parser::expect_no_arguments(function)?;
let out_property =
TemplateFunction::new(self_property, |items| Ok(items.len().try_into()?));
language.wrap_integer(out_property)
}
// No "join"
"map" => build_map_operation(language, build_ctx, self_property, function, wrap_item)?,
_ => return Err(TemplateParseError::no_such_method("List", function)),
@ -1536,6 +1553,9 @@ mod tests {
language.wrap_string(Literal("sep".to_owned()))
});
insta::assert_snapshot!(env.render_ok(r#""".lines().len()"#), @"0");
insta::assert_snapshot!(env.render_ok(r#""a\nb\nc".lines().len()"#), @"3");
insta::assert_snapshot!(env.render_ok(r#""".lines().join("|")"#), @"");
insta::assert_snapshot!(env.render_ok(r#""a\nb\nc".lines().join("|")"#), @"a|b|c");
// Null separator
@ -1633,6 +1653,10 @@ mod tests {
language.wrap_string(Literal("description 1".to_owned()))
});
insta::assert_snapshot!(env.render_ok(r#""".len()"#), @"0");
insta::assert_snapshot!(env.render_ok(r#""foo".len()"#), @"3");
insta::assert_snapshot!(env.render_ok(r#""💩".len()"#), @"4");
insta::assert_snapshot!(env.render_ok(r#""fooo".contains("foo")"#), @"true");
insta::assert_snapshot!(env.render_ok(r#""foo".contains("fooo")"#), @"false");
insta::assert_snapshot!(env.render_ok(r#"description.contains("description")"#), @"true");

View file

@ -26,17 +26,18 @@ fn test_log_parents() {
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
test_env.jj_cmd_ok(&repo_path, &["new", "@", "@-"]);
let template = r#"commit_id ++ "\nP: " ++ parents.map(|c| c.commit_id()) ++ "\n""#;
let template =
r#"commit_id ++ "\nP: " ++ parents.len() ++ " " ++ parents.map(|c| c.commit_id()) ++ "\n""#;
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-T", template]);
insta::assert_snapshot!(stdout, @r###"
@ c067170d4ca1bc6162b64f7550617ec809647f84
P: 4db490c88528133d579540b6900b8098f0c17701 230dd059e1b059aefc0da06a2e5a7dbf22362f22
P: 2 4db490c88528133d579540b6900b8098f0c17701 230dd059e1b059aefc0da06a2e5a7dbf22362f22
4db490c88528133d579540b6900b8098f0c17701
P: 230dd059e1b059aefc0da06a2e5a7dbf22362f22
P: 1 230dd059e1b059aefc0da06a2e5a7dbf22362f22
230dd059e1b059aefc0da06a2e5a7dbf22362f22
P: 0000000000000000000000000000000000000000
P: 1 0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
P:
P: 0
"###);
let template = r#"parents.map(|c| c.commit_id().shortest(4))"#;

View file

@ -105,6 +105,7 @@ No methods are defined.
A list can be implicitly converted to `Boolean`. The following methods are
defined.
* `.len() -> Integer`: Number of elements in the list.
* `.join(separator: Template) -> Template`: Concatenate elements with
the given `separator`.
* `.map(|item| expression) -> ListTemplate`: Apply template `expression`
@ -164,6 +165,7 @@ The following methods are defined.
A string can be implicitly converted to `Boolean`. The following methods are
defined.
* `.len() -> Integer`: Length in UTF-8 bytes.
* `.contains(needle: Template) -> Boolean`
* `.first_line() -> String`
* `.lines() -> List<String>`: Split into lines excluding newline characters.