[PATCH v2] templates: add substring and string length operations

Rodrigo Damazio Bovendorp rdamazio at google.com
Fri Jul 14 23:42:07 UTC 2017


# HG changeset patch
# User Rodrigo Damazio Bovendorp <rdamazio at google.com>
# Date 1500075683 25200
#      Fri Jul 14 16:41:23 2017 -0700
# Node ID c4bac4ea7b1ea923d6ba4299cd9c974469b39cb0
# Parent  c0d8de2724ce6240d2a4241aff78ce2ee92359c2
templates: add substring and string length operations

This will allow substr(text, start, end) and strlen(text) in templates,
permitting various text formatting, such as making a (non-graphing) log line be
limited to terminal width ("substr(desc, 0, termwidth)")

diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -362,6 +362,11 @@
         return ""
     return pycompat.bytestr(thing)
 
+ at templatefilter('strlen')
+def stringlen(text):
+    """Any text. Turns the value into its length."""
+    return len(text)
+
 @templatefilter('stripdir')
 def stripdir(text):
     """Treat the text as path and strip a directory level, if
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -1015,6 +1015,25 @@
         # i18n: "sub" is a keyword
         raise error.ParseError(_("sub got an invalid replacement: %s") % rpl)
 
+ at templatefunc('substr(text, start[, end])')
+def substring(context, mapping, args):
+    """Returns a substring of the given text. Negative indices reference the end
+    of the string."""
+    if len(args) < 2 or len(args) > 3:
+        raise error.ParseError(
+            _("substring expects two or three arguments, got %d") % len(args))
+
+    text = evalstring(context, mapping, args[0])
+    start = evalinteger(context, mapping, args[1],
+                      _("start expects an integer index"))
+    end = len(text)
+    if len(args) > 2:
+        end = evalinteger(context, mapping, args[2],
+                          _("end expects an integer index"))
+
+    # Python's [] already handles start and end boundary conditions.
+    return text[start:end]
+
 @templatefunc('startswith(pattern, text)')
 def startswith(context, mapping, args):
     """Returns the value from the "text" argument
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
@@ -4011,6 +4011,39 @@
   o  line 1
      line 2
 
+Test stringlen and substring
+Full desc is "Modify, add, remove, rename".
+String idxs:  012345678901
+Reverse string idxs:          10987654321
+
+  $ hg log -R a -r . --template '{desc|strlen}\n'
+  27
+  $ hg log -R a -r . --template '{substr(desc, 5)}\n'
+  y, add, remove, rename
+  $ hg log -R a -r . --template '{substr(desc, -10)}\n'
+  ve, rename
+  $ hg log -R a -r . --template '{substr(desc, 5, 10)}\n'
+  y, ad
+  $ hg log -R a -r . --template '{substr(desc, 5, -10)}\n'
+  y, add, remo
+  $ hg log -R a -r . --template '{substr(desc, 5, strlen(desc) - 10)}\n'
+  y, add, remo
+  $ hg log -R a -r . --template '{substr(desc, -10, -3)}\n'
+  ve, ren
+
+Test substr with invalid indices
+
+  $ hg log -R a -r . --template '{substr(desc, 5, 200)}\n'
+  y, add, remove, rename
+  $ hg log -R a -r . --template '{substr(desc, 10, 5)}\n'
+  
+  $ hg log -R a -r . --template '{substr(desc, 100, 200)}\n'
+  
+  $ hg log -R a -r . --template '{substr(desc, -100, -50)}\n'
+  
+  $ hg log -R a -r . --template '{substr(desc, -50, -100)}\n'
+  
+
 Test bad template with better error message
 
   $ hg log -Gv -R a --template '{desc|user()}'


More information about the Mercurial-devel mailing list