mercurial/registrar.py
changeset 28392 b983a2f04987
parent 27585 60bf90eb8bf8
child 28393 ac11ba7c2e56
--- a/mercurial/registrar.py	Tue Mar 08 23:04:53 2016 +0900
+++ b/mercurial/registrar.py	Tue Mar 08 23:04:53 2016 +0900
@@ -126,3 +126,82 @@
         while self._list:
             func, decorator = self._list.pop(0)
             decorator(func)
+
+class _funcregistrarbase(object):
+    """Base of decorator to register a fuction for specific purpose
+
+    This decorator stores decorated functions into own dict 'table'.
+
+    The least derived class can be defined by overriding 'formatdoc',
+    for example::
+
+        class keyword(_funcregistrarbase):
+            _docformat = ":%s: %s"
+
+    This should be used as below:
+
+        keyword = registrar.keyword()
+
+        @keyword('bar')
+        def barfunc(*args, **kwargs):
+            '''Explanation of bar keyword ....
+            '''
+            pass
+
+    In this case:
+
+    - 'barfunc' is stored as 'bar' in '_table' of an instance 'keyword' above
+    - 'barfunc.__doc__' becomes ":bar: Explanation of bar keyword"
+    """
+    def __init__(self, table=None):
+        if table is None:
+            self._table = {}
+        else:
+            self._table = table
+
+    def __call__(self, decl, *args, **kwargs):
+        return lambda func: self._doregister(func, decl, *args, **kwargs)
+
+    def _doregister(self, func, decl, *args, **kwargs):
+        name = self._getname(decl)
+
+        if func.__doc__ and not util.safehasattr(func, '_origdoc'):
+            doc = func.__doc__.strip()
+            func._origdoc = doc
+            func.__doc__ = self._formatdoc(decl, doc)
+
+        self._table[name] = func
+        self._extrasetup(name, func, *args, **kwargs)
+
+        return func
+
+    def _parsefuncdecl(self, decl):
+        """Parse function declaration and return the name of function in it
+        """
+        i = decl.find('(')
+        if i >= 0:
+            return decl[:i]
+        else:
+            return decl
+
+    def _getname(self, decl):
+        """Return the name of the registered function from decl
+
+        Derived class should override this, if it allows more
+        descriptive 'decl' string than just a name.
+        """
+        return decl
+
+    _docformat = None
+
+    def _formatdoc(self, decl, doc):
+        """Return formatted document of the registered function for help
+
+        'doc' is '__doc__.strip()' of the registered function.
+        """
+        return self._docformat % (decl, doc)
+
+    def _extrasetup(self, name, func):
+        """Execute exra setup for registered function, if needed
+        """
+        pass