diff --git a/docs/templates.md b/docs/templates.md index 05a6eee474..4238fd2a57 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -56,6 +56,8 @@ The following operators are supported. The following functions are defined. +* `fill(width: Integer, content: Template) -> Template`: Fill lines at + the given `width`. * `indent(prefix: Template, content: Template) -> Template`: Indent non-empty lines by the given `prefix`. * `label(label: Template, content: Template) -> Template`: Apply label to diff --git a/src/template_parser.rs b/src/template_parser.rs index 55dc4780e0..132573ee26 100644 --- a/src/template_parser.rs +++ b/src/template_parser.rs @@ -1071,6 +1071,16 @@ fn build_global_function<'a, L: TemplateLanguage<'a>>( function: &FunctionCallNode, ) -> TemplateParseResult> { let property = match function.name { + "fill" => { + let [width_node, content_node] = expect_exact_arguments(function)?; + let width = expect_integer_expression(language, width_node)?; + let content = build_expression(language, content_node)?.into_template(); + let template = ReformatTemplate::new(content, move |context, formatter, recorded| { + let width = width.extract(context).try_into().unwrap_or(0); + text_util::write_wrapped(formatter, recorded, width) + }); + language.wrap_template(template) + } "indent" => { let [prefix_node, content_node] = expect_exact_arguments(function)?; let prefix = build_expression(language, prefix_node)?.into_template(); diff --git a/tests/test_templater.rs b/tests/test_templater.rs index 7f88c69714..c3c6ebbadb 100644 --- a/tests/test_templater.rs +++ b/tests/test_templater.rs @@ -332,6 +332,45 @@ fn test_templater_signature() { insta::assert_snapshot!(render(r#"author.username()"#), @"x"); } +#[test] +fn test_templater_fill_function() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + let render = |template| get_colored_template_output(&test_env, &repo_path, "@-", template); + + insta::assert_snapshot!( + render(r#"fill(20, "The quick fox jumps over the " ++ + label("error", "lazy") ++ " dog\n")"#), + @r###" + The quick fox jumps + over the lazy dog + "###); + + // Word-wrap, then indent + insta::assert_snapshot!( + render(r#""START marker to help insta\n" ++ + indent(" ", fill(20, "The quick fox jumps over the " ++ + label("error", "lazy") ++ " dog\n"))"#), + @r###" + START marker to help insta + The quick fox jumps + over the lazy dog + "###); + + // Word-wrap indented (no special handling for leading spaces) + insta::assert_snapshot!( + render(r#""START marker to help insta\n" ++ + fill(20, indent(" ", "The quick fox jumps over the " ++ + label("error", "lazy") ++ " dog\n"))"#), + @r###" + START marker to help insta + The quick fox + jumps over the lazy + dog + "###); +} + #[test] fn test_templater_indent_function() { let test_env = TestEnvironment::default();