Patchwork [2,of,4,V2] templater: introduce startswith function

login
register
mail settings
Submitter Ryan McElroy
Date June 30, 2014, 8:16 a.m.
Message ID <761db1c368e2765cb485.1404116180@nexus.gateway.2wire.net>
Download mbox | patch
Permalink /patch/5079/
State Accepted
Commit 4a445dc5abff7f0e971222bea1bf04ce02bead5e
Headers show

Comments

Ryan McElroy - June 30, 2014, 8:16 a.m.
# HG changeset patch
# User Ryan McElroy <rmcelroy@fb.com>
# Date 1402620817 25200
#      Thu Jun 12 17:53:37 2014 -0700
# Node ID 761db1c368e2765cb485789eb4d237dad32c76c4
# Parent  45d7b890bf0da308b743180101acd80e1d147620
templater: introduce startswith function

This function returns a string only if it starts with a given string.
It is particularly useful when combined with splitlines and/or used with
conditionals that fail when empty strings are passed in to take action
based on the contents of a line.
Pierre-Yves David - July 1, 2014, 11:33 a.m.
On 06/30/2014 10:16 AM, Ryan McElroy wrote:
> # HG changeset patch
> # User Ryan McElroy <rmcelroy@fb.com>
> # Date 1402620817 25200
> #      Thu Jun 12 17:53:37 2014 -0700
> # Node ID 761db1c368e2765cb485789eb4d237dad32c76c4
> # Parent  45d7b890bf0da308b743180101acd80e1d147620
> templater: introduce startswith function
>
> This function returns a string only if it starts with a given string.
> It is particularly useful when combined with splitlines and/or used with
> conditionals that fail when empty strings are passed in to take action
> based on the contents of a line.
>
> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/help/templates.txt
> --- a/mercurial/help/templates.txt	Thu Jun 12 17:45:41 2014 -0700
> +++ b/mercurial/help/templates.txt	Thu Jun 12 17:53:37 2014 -0700
> @@ -66,6 +66,8 @@
>
>   - shortest(node)
>
> +- startswith(string, text)
> +
>   - strip(text[, chars])
>
>   - sub(pat, repl, expr)
> @@ -124,3 +126,7 @@
>   - Mark the working copy parent with '@'::
>
>      $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n"
> +
> +- Show only commit descriptions that start with "template"::
> +
> +   $ hg log --template "{startswith(\"template\", firstline(desc))}\n"
> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/templater.py
> --- a/mercurial/templater.py	Thu Jun 12 17:45:41 2014 -0700
> +++ b/mercurial/templater.py	Thu Jun 12 17:53:37 2014 -0700
> @@ -466,6 +466,17 @@
>       src = stringify(_evalifliteral(args[2], context, mapping))
>       yield re.sub(pat, rpl, src)
>
> +def startswith(context, mapping, args):
> +    if len(args) != 2:
> +        raise error.ParseError(_("startswith expects two arguments"))
> +
> +    patn = stringify(args[0][0](context, mapping, args[0][1]))
> +    text = stringify(args[1][0](context, mapping, args[1][1]))
> +    if text.startswith(patn):
> +        return text
> +    return ''

This `return ''` is bugging me a little. I assume this is standard 
practice in template? Is there a plan to clean this up?
Ryan McElroy - July 1, 2014, 4:32 p.m.
It is somewhat standard (see, for example
https://github.com/vmg/hg-stable/blob/master/mercurial/templatefilters.py#L79),
plus it is the only stingify-able way to convey falseness. Most remplater
functions and filters stringify all their arguments, and the only way to
pass a falsy value is the empty string.

~Ryan


On Tue, Jul 1, 2014 at 4:33 AM, Pierre-Yves David <
pierre-yves.david@ens-lyon.org> wrote:

>
>
> On 06/30/2014 10:16 AM, Ryan McElroy wrote:
>
>> # HG changeset patch
>> # User Ryan McElroy <rmcelroy@fb.com>
>> # Date 1402620817 25200
>> #      Thu Jun 12 17:53:37 2014 -0700
>> # Node ID 761db1c368e2765cb485789eb4d237dad32c76c4
>> # Parent  45d7b890bf0da308b743180101acd80e1d147620
>> templater: introduce startswith function
>>
>> This function returns a string only if it starts with a given string.
>> It is particularly useful when combined with splitlines and/or used with
>> conditionals that fail when empty strings are passed in to take action
>> based on the contents of a line.
>>
>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/help/templates.txt
>> --- a/mercurial/help/templates.txt      Thu Jun 12 17:45:41 2014 -0700
>> +++ b/mercurial/help/templates.txt      Thu Jun 12 17:53:37 2014 -0700
>> @@ -66,6 +66,8 @@
>>
>>   - shortest(node)
>>
>> +- startswith(string, text)
>> +
>>   - strip(text[, chars])
>>
>>   - sub(pat, repl, expr)
>> @@ -124,3 +126,7 @@
>>   - Mark the working copy parent with '@'::
>>
>>      $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n"
>> +
>> +- Show only commit descriptions that start with "template"::
>> +
>> +   $ hg log --template "{startswith(\"template\", firstline(desc))}\n"
>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/templater.py
>> --- a/mercurial/templater.py    Thu Jun 12 17:45:41 2014 -0700
>> +++ b/mercurial/templater.py    Thu Jun 12 17:53:37 2014 -0700
>> @@ -466,6 +466,17 @@
>>       src = stringify(_evalifliteral(args[2], context, mapping))
>>       yield re.sub(pat, rpl, src)
>>
>> +def startswith(context, mapping, args):
>> +    if len(args) != 2:
>> +        raise error.ParseError(_("startswith expects two arguments"))
>> +
>> +    patn = stringify(args[0][0](context, mapping, args[0][1]))
>> +    text = stringify(args[1][0](context, mapping, args[1][1]))
>> +    if text.startswith(patn):
>> +        return text
>> +    return ''
>>
>
> This `return ''` is bugging me a little. I assume this is standard
> practice in template? Is there a plan to clean this up?
>
>
> --
> Pierre-Yves David
>
Sean Farley - July 1, 2014, 9:25 p.m.
Pierre-Yves David writes:

> On 06/30/2014 10:16 AM, Ryan McElroy wrote:
>> # HG changeset patch
>> # User Ryan McElroy <rmcelroy@fb.com>
>> # Date 1402620817 25200
>> #      Thu Jun 12 17:53:37 2014 -0700
>> # Node ID 761db1c368e2765cb485789eb4d237dad32c76c4
>> # Parent  45d7b890bf0da308b743180101acd80e1d147620
>> templater: introduce startswith function
>>
>> This function returns a string only if it starts with a given string.
>> It is particularly useful when combined with splitlines and/or used with
>> conditionals that fail when empty strings are passed in to take action
>> based on the contents of a line.
>>
>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/help/templates.txt
>> --- a/mercurial/help/templates.txt	Thu Jun 12 17:45:41 2014 -0700
>> +++ b/mercurial/help/templates.txt	Thu Jun 12 17:53:37 2014 -0700
>> @@ -66,6 +66,8 @@
>>
>>   - shortest(node)
>>
>> +- startswith(string, text)
>> +
>>   - strip(text[, chars])
>>
>>   - sub(pat, repl, expr)
>> @@ -124,3 +126,7 @@
>>   - Mark the working copy parent with '@'::
>>
>>      $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n"
>> +
>> +- Show only commit descriptions that start with "template"::
>> +
>> +   $ hg log --template "{startswith(\"template\", firstline(desc))}\n"
>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/templater.py
>> --- a/mercurial/templater.py	Thu Jun 12 17:45:41 2014 -0700
>> +++ b/mercurial/templater.py	Thu Jun 12 17:53:37 2014 -0700
>> @@ -466,6 +466,17 @@
>>       src = stringify(_evalifliteral(args[2], context, mapping))
>>       yield re.sub(pat, rpl, src)
>>
>> +def startswith(context, mapping, args):
>> +    if len(args) != 2:
>> +        raise error.ParseError(_("startswith expects two arguments"))
>> +
>> +    patn = stringify(args[0][0](context, mapping, args[0][1]))
>> +    text = stringify(args[1][0](context, mapping, args[1][1]))
>> +    if text.startswith(patn):
>> +        return text
>> +    return ''
>
> This `return ''` is bugging me a little. I assume this is standard 
> practice in template? Is there a plan to clean this up?

If you would prefer, you could do something like:

if not text.startswith(patn):
  text = ''
return text

but that seemed like too much nitpicking for me.
Pierre-Yves David - July 5, 2014, 9:01 p.m.
On 07/01/2014 11:25 PM, Sean Farley wrote:
>
> Pierre-Yves David writes:
>
>> On 06/30/2014 10:16 AM, Ryan McElroy wrote:
>>> # HG changeset patch
>>> # User Ryan McElroy <rmcelroy@fb.com>
>>> # Date 1402620817 25200
>>> #      Thu Jun 12 17:53:37 2014 -0700
>>> # Node ID 761db1c368e2765cb485789eb4d237dad32c76c4
>>> # Parent  45d7b890bf0da308b743180101acd80e1d147620
>>> templater: introduce startswith function
>>>
>>> This function returns a string only if it starts with a given string.
>>> It is particularly useful when combined with splitlines and/or used with
>>> conditionals that fail when empty strings are passed in to take action
>>> based on the contents of a line.
>>>
>>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/help/templates.txt
>>> --- a/mercurial/help/templates.txt	Thu Jun 12 17:45:41 2014 -0700
>>> +++ b/mercurial/help/templates.txt	Thu Jun 12 17:53:37 2014 -0700
>>> @@ -66,6 +66,8 @@
>>>
>>>    - shortest(node)
>>>
>>> +- startswith(string, text)
>>> +
>>>    - strip(text[, chars])
>>>
>>>    - sub(pat, repl, expr)
>>> @@ -124,3 +126,7 @@
>>>    - Mark the working copy parent with '@'::
>>>
>>>       $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n"
>>> +
>>> +- Show only commit descriptions that start with "template"::
>>> +
>>> +   $ hg log --template "{startswith(\"template\", firstline(desc))}\n"
>>> diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/templater.py
>>> --- a/mercurial/templater.py	Thu Jun 12 17:45:41 2014 -0700
>>> +++ b/mercurial/templater.py	Thu Jun 12 17:53:37 2014 -0700
>>> @@ -466,6 +466,17 @@
>>>        src = stringify(_evalifliteral(args[2], context, mapping))
>>>        yield re.sub(pat, rpl, src)
>>>
>>> +def startswith(context, mapping, args):
>>> +    if len(args) != 2:
>>> +        raise error.ParseError(_("startswith expects two arguments"))
>>> +
>>> +    patn = stringify(args[0][0](context, mapping, args[0][1]))
>>> +    text = stringify(args[1][0](context, mapping, args[1][1]))
>>> +    if text.startswith(patn):
>>> +        return text
>>> +    return ''
>>
>> This `return ''` is bugging me a little. I assume this is standard
>> practice in template? Is there a plan to clean this up?
>
> If you would prefer, you could do something like:
>
> if not text.startswith(patn):
>    text = ''
> return text
>
> but that seemed like too much nitpicking for me.
>

Patch

diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/help/templates.txt
--- a/mercurial/help/templates.txt	Thu Jun 12 17:45:41 2014 -0700
+++ b/mercurial/help/templates.txt	Thu Jun 12 17:53:37 2014 -0700
@@ -66,6 +66,8 @@ 
 
 - shortest(node)
 
+- startswith(string, text)
+
 - strip(text[, chars])
 
 - sub(pat, repl, expr)
@@ -124,3 +126,7 @@ 
 - Mark the working copy parent with '@'::
 
    $ hg log --template "{ifcontains(rev, revset('.'), '@')}\n"
+
+- Show only commit descriptions that start with "template"::
+
+   $ hg log --template "{startswith(\"template\", firstline(desc))}\n"
diff -r 45d7b890bf0d -r 761db1c368e2 mercurial/templater.py
--- a/mercurial/templater.py	Thu Jun 12 17:45:41 2014 -0700
+++ b/mercurial/templater.py	Thu Jun 12 17:53:37 2014 -0700
@@ -466,6 +466,17 @@ 
     src = stringify(_evalifliteral(args[2], context, mapping))
     yield re.sub(pat, rpl, src)
 
+def startswith(context, mapping, args):
+    if len(args) != 2:
+        raise error.ParseError(_("startswith expects two arguments"))
+
+    patn = stringify(args[0][0](context, mapping, args[0][1]))
+    text = stringify(args[1][0](context, mapping, args[1][1]))
+    if text.startswith(patn):
+        return text
+    return ''
+
+
 methods = {
     "string": lambda e, c: (runstring, e[1]),
     "rawstring": lambda e, c: (runrawstring, e[1]),
@@ -490,6 +501,7 @@ 
     "revset": revset,
     "rstdoc": rstdoc,
     "shortest": shortest,
+    "startswith": startswith,
     "strip": strip,
     "sub": sub,
 }
diff -r 45d7b890bf0d -r 761db1c368e2 tests/test-command-template.t
--- a/tests/test-command-template.t	Thu Jun 12 17:45:41 2014 -0700
+++ b/tests/test-command-template.t	Thu Jun 12 17:53:37 2014 -0700
@@ -1884,3 +1884,30 @@ 
   |  foo other 3
   o  foo line 1
      foo line 2
+
+Test startswith
+  $ hg log -Gv -R a --template "{startswith(desc)}"
+  hg: parse error: startswith expects two arguments
+  [255]
+
+  $ hg log -Gv -R a --template "{startswith('line', desc)}"
+  @
+  |
+  o
+  |
+  o
+  
+  o
+  |\
+  | o
+  | |
+  o |
+  |/
+  o
+  |
+  o
+  |
+  o
+  |
+  o  line 1
+     line 2