comparison mercurial/dispatch.py @ 37134:6890b7e991a4

help: supporting both help and doc for aliases This allows an alias to be definted like: [alias] lj = log -Tjson lj:help = [-r REV] lj:doc = Shows the revision log in JSON format. Differential Revision: https://phab.mercurial-scm.org/D2678
author Rodrigo Damazio <rdamazio@google.com>
date Sun, 04 Mar 2018 17:11:33 -0500
parents a8a902d7176e
children aa55c5354b8f
comparison
equal deleted inserted replaced
37133:a2a6755a3def 37134:6890b7e991a4
448 regex = '|'.join(replacemap.keys()).replace('$', br'\$') 448 regex = '|'.join(replacemap.keys()).replace('$', br'\$')
449 r = re.compile(regex) 449 r = re.compile(regex)
450 return r.sub(lambda x: replacemap[x.group()], cmd) 450 return r.sub(lambda x: replacemap[x.group()], cmd)
451 451
452 class cmdalias(object): 452 class cmdalias(object):
453 def __init__(self, name, definition, cmdtable, source): 453 def __init__(self, ui, name, definition, cmdtable, source):
454 self.name = self.cmd = name 454 self.name = self.cmd = name
455 self.cmdname = '' 455 self.cmdname = ''
456 self.definition = definition 456 self.definition = definition
457 self.fn = None 457 self.fn = None
458 self.givenargs = [] 458 self.givenargs = []
475 if not self.definition: 475 if not self.definition:
476 self.badalias = _("no definition for alias '%s'") % self.name 476 self.badalias = _("no definition for alias '%s'") % self.name
477 return 477 return
478 478
479 if self.definition.startswith('!'): 479 if self.definition.startswith('!'):
480 shdef = self.definition[1:]
480 self.shell = True 481 self.shell = True
481 def fn(ui, *args): 482 def fn(ui, *args):
482 env = {'HG_ARGS': ' '.join((self.name,) + args)} 483 env = {'HG_ARGS': ' '.join((self.name,) + args)}
483 def _checkvar(m): 484 def _checkvar(m):
484 if m.groups()[0] == '$': 485 if m.groups()[0] == '$':
488 else: 489 else:
489 ui.debug("No argument found for substitution " 490 ui.debug("No argument found for substitution "
490 "of %i variable in alias '%s' definition.\n" 491 "of %i variable in alias '%s' definition.\n"
491 % (int(m.groups()[0]), self.name)) 492 % (int(m.groups()[0]), self.name))
492 return '' 493 return ''
493 cmd = re.sub(br'\$(\d+|\$)', _checkvar, self.definition[1:]) 494 cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef)
494 cmd = aliasinterpolate(self.name, args, cmd) 495 cmd = aliasinterpolate(self.name, args, cmd)
495 return ui.system(cmd, environ=env, 496 return ui.system(cmd, environ=env,
496 blockedtag='alias_%s' % self.name) 497 blockedtag='alias_%s' % self.name)
497 self.fn = fn 498 self.fn = fn
499 self._populatehelp(ui, name, shdef, self.fn)
498 return 500 return
499 501
500 try: 502 try:
501 args = pycompat.shlexsplit(self.definition) 503 args = pycompat.shlexsplit(self.definition)
502 except ValueError as inst: 504 except ValueError as inst:
514 self.givenargs = args 516 self.givenargs = args
515 517
516 try: 518 try:
517 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1] 519 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
518 if len(tableentry) > 2: 520 if len(tableentry) > 2:
519 self.fn, self.opts, self.help = tableentry 521 self.fn, self.opts, cmdhelp = tableentry
520 else: 522 else:
521 self.fn, self.opts = tableentry 523 self.fn, self.opts = tableentry
522 524 cmdhelp = None
523 if self.help.startswith("hg " + cmd): 525
524 # drop prefix in old-style help lines so hg shows the alias 526 self._populatehelp(ui, name, cmd, self.fn, cmdhelp)
525 self.help = self.help[4 + len(cmd):]
526 self.__doc__ = self.fn.__doc__
527 527
528 except error.UnknownCommand: 528 except error.UnknownCommand:
529 self.badalias = (_("alias '%s' resolves to unknown command '%s'") 529 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
530 % (self.name, cmd)) 530 % (self.name, cmd))
531 self.unknowncmd = True 531 self.unknowncmd = True
532 except error.AmbiguousCommand: 532 except error.AmbiguousCommand:
533 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'") 533 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
534 % (self.name, cmd)) 534 % (self.name, cmd))
535
536 def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None):
537 self.help = ui.config('alias', '%s:help' % name, defaulthelp or '')
538 if self.help and self.help.startswith("hg " + cmd):
539 # drop prefix in old-style help lines so hg shows the alias
540 self.help = self.help[4 + len(cmd):]
541
542 self.__doc__ = ui.config('alias', '%s:doc' % name, fn.__doc__)
535 543
536 @property 544 @property
537 def args(self): 545 def args(self):
538 args = pycompat.maplist(util.expandpath, self.givenargs) 546 args = pycompat.maplist(util.expandpath, self.givenargs)
539 return aliasargs(self.fn, args) 547 return aliasargs(self.fn, args)
575 raise 583 raise
576 584
577 class lazyaliasentry(object): 585 class lazyaliasentry(object):
578 """like a typical command entry (func, opts, help), but is lazy""" 586 """like a typical command entry (func, opts, help), but is lazy"""
579 587
580 def __init__(self, name, definition, cmdtable, source): 588 def __init__(self, ui, name, definition, cmdtable, source):
589 self.ui = ui
581 self.name = name 590 self.name = name
582 self.definition = definition 591 self.definition = definition
583 self.cmdtable = cmdtable.copy() 592 self.cmdtable = cmdtable.copy()
584 self.source = source 593 self.source = source
585 594
586 @util.propertycache 595 @util.propertycache
587 def _aliasdef(self): 596 def _aliasdef(self):
588 return cmdalias(self.name, self.definition, self.cmdtable, self.source) 597 return cmdalias(self.ui, self.name, self.definition, self.cmdtable,
598 self.source)
589 599
590 def __getitem__(self, n): 600 def __getitem__(self, n):
591 aliasdef = self._aliasdef 601 aliasdef = self._aliasdef
592 if n == 0: 602 if n == 0:
593 return aliasdef 603 return aliasdef
607 617
608 def addaliases(ui, cmdtable): 618 def addaliases(ui, cmdtable):
609 # aliases are processed after extensions have been loaded, so they 619 # aliases are processed after extensions have been loaded, so they
610 # may use extension commands. Aliases can also use other alias definitions, 620 # may use extension commands. Aliases can also use other alias definitions,
611 # but only if they have been defined prior to the current definition. 621 # but only if they have been defined prior to the current definition.
612 for alias, definition in ui.configitems('alias'): 622 for alias, definition in ui.configitems('alias', ignoresub=True):
613 try: 623 try:
614 if cmdtable[alias].definition == definition: 624 if cmdtable[alias].definition == definition:
615 continue 625 continue
616 except (KeyError, AttributeError): 626 except (KeyError, AttributeError):
617 # definition might not exist or it might not be a cmdalias 627 # definition might not exist or it might not be a cmdalias
618 pass 628 pass
619 629
620 source = ui.configsource('alias', alias) 630 source = ui.configsource('alias', alias)
621 entry = lazyaliasentry(alias, definition, cmdtable, source) 631 entry = lazyaliasentry(ui, alias, definition, cmdtable, source)
622 cmdtable[alias] = entry 632 cmdtable[alias] = entry
623 633
624 def _parse(ui, args): 634 def _parse(ui, args):
625 options = {} 635 options = {}
626 cmdoptions = {} 636 cmdoptions = {}