diff --git a/mercurial/registrar.py b/mercurial/registrar.py --- a/mercurial/registrar.py +++ b/mercurial/registrar.py @@ -126,3 +126,82 @@ class delayregistrar(object): 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