Patchwork templater: introduce indent function

login
register
mail settings
Submitter Ryan McElroy
Date April 4, 2015, 8:19 a.m.
Message ID <e2af17e4887916089a49.1428135592@devbig105.prn2.facebook.com>
Download mbox | patch
Permalink /patch/8497/
State Superseded
Commit ef8956aa8755d84a6894aa609dfa7ec2e51fed5a
Headers show

Comments

Ryan McElroy - April 4, 2015, 8:19 a.m.
# HG changeset patch
# User Ryan McElroy <rmcelroy@fb.com>
# Date 1428134632 25200
#      Sat Apr 04 01:03:52 2015 -0700
# Node ID e2af17e4887916089a49b2d3331a725c840fbce6
# Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
templater: introduce indent function
Yuya Nishihara - April 4, 2015, 1:23 p.m.
On Sat, 4 Apr 2015 01:19:52 -0700, Ryan McElroy wrote:
> # HG changeset patch
> # User Ryan McElroy <rmcelroy@fb.com>
> # Date 1428134632 25200
> #      Sat Apr 04 01:03:52 2015 -0700
> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
> templater: introduce indent function
> 
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>      else:
>          return text.ljust(width, fillchar)
>  
> +def indent(context, mapping, args):
> +    """:indent(text, indentchars): Indents all non-empty lines except the first
> +    with the characters given in the indentchars string.
> +    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
> +    """
> +    if len(args) != 2:
> +        # i18n: "indent" is a keyword
> +        raise error.ParseError(_("indent() expects two arguments"))
> +
> +    text = args[0][0](context, mapping, args[0][1])
> +    indent = args[1][0](context, mapping, args[1][1])

They'll need stringify() to evaluate generator and avoid TypeError.

  {indent(sub(desc, "foo", "bar"), "  ")}
  {indent(date, "  ")}

Regards,
Gregory Szorc - April 4, 2015, 3:51 p.m.
On Sat, Apr 4, 2015 at 1:19 AM, Ryan McElroy <rmcelroy@fb.com> wrote:

> # HG changeset patch
> # User Ryan McElroy <rmcelroy@fb.com>
> # Date 1428134632 25200
> #      Sat Apr 04 01:03:52 2015 -0700
> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
> templater: introduce indent function
>
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>      else:
>          return text.ljust(width, fillchar)
>
> +def indent(context, mapping, args):
> +    """:indent(text, indentchars): Indents all non-empty lines except the
> first
> +    with the characters given in the indentchars string.
> +    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
> +    """
>

Is this not equivalent to "fill" (the function or filter)?
Durham Goode - April 4, 2015, 8:31 p.m.
On 4/4/15 1:19 AM, Ryan McElroy wrote:
> # HG changeset patch
> # User Ryan McElroy <rmcelroy@fb.com>
> # Date 1428134632 25200
> #      Sat Apr 04 01:03:52 2015 -0700
> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
> templater: introduce indent function
>
> diff --git a/mercurial/templater.py b/mercurial/templater.py
> --- a/mercurial/templater.py
> +++ b/mercurial/templater.py
> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>       else:
>           return text.ljust(width, fillchar)
>   
> +def indent(context, mapping, args):
> +    """:indent(text, indentchars): Indents all non-empty lines except the first
> +    with the characters given in the indentchars string.
> +    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
> +    """
Why doesn't it indent the first line?
Ryan McElroy - April 10, 2015, 6:11 a.m.
On 4/4/2015 6:23 AM, Yuya Nishihara wrote:
> On Sat, 4 Apr 2015 01:19:52 -0700, Ryan McElroy wrote:
>> # HG changeset patch
>> # User Ryan McElroy <rmcelroy@fb.com>
>> # Date 1428134632 25200
>> #      Sat Apr 04 01:03:52 2015 -0700
>> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
>> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
>> templater: introduce indent function
>>
>> diff --git a/mercurial/templater.py b/mercurial/templater.py
>> --- a/mercurial/templater.py
>> +++ b/mercurial/templater.py
>> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>>       else:
>>           return text.ljust(width, fillchar)
>>   
>> +def indent(context, mapping, args):
>> +    """:indent(text, indentchars): Indents all non-empty lines except the first
>> +    with the characters given in the indentchars string.
>> +    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
>> +    """
>> +    if len(args) != 2:
>> +        # i18n: "indent" is a keyword
>> +        raise error.ParseError(_("indent() expects two arguments"))
>> +
>> +    text = args[0][0](context, mapping, args[0][1])
>> +    indent = args[1][0](context, mapping, args[1][1])
> They'll need stringify() to evaluate generator and avoid TypeError.
>
>    {indent(sub(desc, "foo", "bar"), "  ")}
>    {indent(date, "  ")}
>
Okay, I'll add this in v2 and add a test. Thanks for noticing.
Ryan McElroy - April 10, 2015, 6:16 a.m.
On 4/4/2015 8:51 AM, Gregory Szorc wrote:
> On Sat, Apr 4, 2015 at 1:19 AM, Ryan McElroy <rmcelroy@fb.com 
> <mailto:rmcelroy@fb.com>> wrote:
>
>     # HG changeset patch
>     # User Ryan McElroy <rmcelroy@fb.com <mailto:rmcelroy@fb.com>>
>     # Date 1428134632 25200
>     #      Sat Apr 04 01:03:52 2015 -0700
>     # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
>     # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
>     templater: introduce indent function
>
>     diff --git a/mercurial/templater.py b/mercurial/templater.py
>     --- a/mercurial/templater.py
>     +++ b/mercurial/templater.py
>     @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>          else:
>              return text.ljust(width, fillchar)
>
>     +def indent(context, mapping, args):
>     +    """:indent(text, indentchars): Indents all non-empty lines
>     except the first
>     +    with the characters given in the indentchars string.
>     +    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
>     +    """
>
>
> Is this not equivalent to "fill" (the function or filter)?
fill behaves... oddly with some characters. see 
http://bz.selenic.com/show_bug.cgi?id=4566
Ryan McElroy - April 10, 2015, 6:18 a.m.
On 4/4/2015 1:31 PM, Durham Goode wrote:
>
>
> On 4/4/15 1:19 AM, Ryan McElroy wrote:
>> # HG changeset patch
>> # User Ryan McElroy <rmcelroy@fb.com>
>> # Date 1428134632 25200
>> #      Sat Apr 04 01:03:52 2015 -0700
>> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
>> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
>> templater: introduce indent function
>>
>> diff --git a/mercurial/templater.py b/mercurial/templater.py
>> --- a/mercurial/templater.py
>> +++ b/mercurial/templater.py
>> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>>       else:
>>           return text.ljust(width, fillchar)
>>   +def indent(context, mapping, args):
>> +    """:indent(text, indentchars): Indents all non-empty lines 
>> except the first
>> +    with the characters given in the indentchars string.
>> +    Example: indent('hello\\nworld', '    ') == "hello\\n world"
>> +    """
> Why doesn't it indent the first line?
For consistency with tabindent, and because I call the same function as 
tabindent, which works this way. The reasoning, I suppose, is that one 
can always indent the first line without a function by simply adding 
spaces or tabs inside the template.
Durham Goode - April 10, 2015, 7:44 p.m.
On 4/9/15 11:18 PM, Ryan McElroy wrote:
> On 4/4/2015 1:31 PM, Durham Goode wrote:
>>
>>
>> On 4/4/15 1:19 AM, Ryan McElroy wrote:
>>> # HG changeset patch
>>> # User Ryan McElroy <rmcelroy@fb.com>
>>> # Date 1428134632 25200
>>> #      Sat Apr 04 01:03:52 2015 -0700
>>> # Node ID e2af17e4887916089a49b2d3331a725c840fbce6
>>> # Parent  4a4018831d2ebc3c9cae9c6613e6a2497b4f0993
>>> templater: introduce indent function
>>>
>>> diff --git a/mercurial/templater.py b/mercurial/templater.py
>>> --- a/mercurial/templater.py
>>> +++ b/mercurial/templater.py
>>> @@ -301,6 +301,20 @@ def pad(context, mapping, args):
>>>       else:
>>>           return text.ljust(width, fillchar)
>>>   +def indent(context, mapping, args):
>>> +    """:indent(text, indentchars): Indents all non-empty lines 
>>> except the first
>>> +    with the characters given in the indentchars string.
>>> +    Example: indent('hello\\nworld', '    ') == "hello\\n world"
>>> +    """
>> Why doesn't it indent the first line?
> For consistency with tabindent, and because I call the same function 
> as tabindent, which works this way. The reasoning, I suppose, is that 
> one can always indent the first line without a function by simply 
> adding spaces or tabs inside the template.
Looks like the tabindent functionality was added in Mar 2006.  I'd vote 
to have indent() indent every line.  This is a chance to remove one more 
anachronism from the code base as we move away from template filters.

If people need the ability to skip only certain lines, we can add an 
optional arg to indent() later.

Patch

diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -301,6 +301,20 @@  def pad(context, mapping, args):
     else:
         return text.ljust(width, fillchar)
 
+def indent(context, mapping, args):
+    """:indent(text, indentchars): Indents all non-empty lines except the first
+    with the characters given in the indentchars string.
+    Example: indent('hello\\nworld', '    ') == "hello\\n    world"
+    """
+    if len(args) != 2:
+        # i18n: "indent" is a keyword
+        raise error.ParseError(_("indent() expects two arguments"))
+
+    text = args[0][0](context, mapping, args[0][1])
+    indent = args[1][0](context, mapping, args[1][1])
+
+    return templatefilters.indent(text, indent)
+
 def get(context, mapping, args):
     """:get(dict, key): Get an attribute/key from an object. Some keywords
     are complex types. This function allows you to obtain the value of an
@@ -571,6 +585,7 @@  funcs = {
     "if": if_,
     "ifcontains": ifcontains,
     "ifeq": ifeq,
+    "indent": indent,
     "join": join,
     "label": label,
     "pad": pad,
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -2548,3 +2548,21 @@  Test word error messages for not enough 
   $ hg log -Gv -R a --template "{word('0', desc, 'o', 'h', 'b', 'o', 'y')}"
   hg: parse error: word expects two or three arguments, got 7
   [255]
+
+Test indent
+
+  $ hg log -T "  {indent(desc, '    ')}\n" -R a
+    future
+    third
+    second
+    merge
+    new head
+    new branch
+    no user, no domain
+    no person
+    other 1
+      other 2
+  
+      other 3
+    line 1
+      line 2