docs: def _dispatch_cmd(self, handler, argv):
          """Introspect sub-command handler signature to determine how to
          dispatch the command. The raw handler provided by the base
          'RawCmdln' class is still supported:
  
              def do_foo(self, argv):
                  # 'argv' is the vector of command line args, argv[0] is
                  # the command name itself (i.e. "foo" or an alias)
                  pass
  
          In addition, if the handler has more than 2 arguments option
          processing is automatically done (using optparse):
  
              @cmdln.option('-v', '--verbose', action='store_true')
              def do_bar(self, subcmd, opts, *args):
                  # subcmd = <"bar" or an alias>
                  # opts = <an optparse.Values instance>
                  if opts.verbose:
                      print "lots of debugging output..."
                  # args = <tuple of arguments>
                  for arg in args:
                      bar(arg)
  
          TODO: explain that "*args" can be other signatures as well.
  
          The `cmdln.option` decorator corresponds to an `add_option()`
          method call on an `optparse.OptionParser` instance.
  
          You can declare a specific number of arguments:
  
              @cmdln.option('-v', '--verbose', action='store_true')
              def do_bar2(self, subcmd, opts, bar_one, bar_two):
                  #...
  
          and an appropriate error message will be raised/printed if the
          command is called with a different number of args.
          """
          co_argcount = handler.__func__.__code__.co_argcount
          if co_argcount == 2:   # handler ::= do_foo(self, argv)
              return handler(argv)
          elif co_argcount >= 3: # handler ::= do_foo(self, subcmd, opts, ...)
              try:
                  optparser = handler.optparser
              except AttributeError:
                  optparser = handler.__func__.optparser = SubCmdOptionParser()
              assert isinstance(optparser, SubCmdOptionParser)
  
              # apply subcommand options' defaults from config files, if any.
              subcmd = handler.__name__.split('do_', 1)[1]
              optparser.set_defaults(**self.get_option_defaults(subcmd))
              
              optparser.set_cmdln_info(self, argv[0])
              try:
                  opts, args = optparser.parse_args(argv[1:])
              except StopOptionProcessing:
                  #TODO: this doesn't really fly for a replacement of
                  #      optparse.py behaviour, does it?
                  return 0 # Normal command termination
  
              try:
                  return handler(argv[0], opts, *args)
              except TypeError:
                  _, ex, _ = sys.exc_info()
                  # Some TypeError's are user errors:
                  #   do_foo() takes at least 4 arguments (3 given)
                  #   do_foo() takes at most 5 arguments (6 given)
                  #   do_foo() takes exactly 5 arguments (6 given)
                  #   do_foo() takes exactly 5 positional arguments (6 given)
                  # Raise CmdlnUserError for these with a suitably
                  # massaged error message.
                  tb = sys.exc_info()[2] # the traceback object
                  if tb.tb_next is not None:
                      # If the traceback is more than one level deep, then the
                      # TypeError do *not* happen on the "handler(...)" call
                      # above. In that we don't want to handle it specially
                      # here: it would falsely mask deeper code errors.
                      raise
                  msg = ex.args[0]
                  match = _INCORRECT_NUM_ARGS_RE.search(msg)
                  if match:
                      msg = list(match.groups())
                      msg[1] = int(msg[1]) - 3
                      if msg[1] == 1:
                          msg[2] = msg[2].replace("arguments", "argument")
                      msg[3] = int(msg[3]) - 3
                      msg = ''.join(map(str, msg))
                      raise CmdlnUserError(msg)
                  else:
                      raise
          else:
              raise CmdlnError("incorrect argcount for %s(): takes %d, must "
                               "take 2 for 'argv' signature or 3+ for 'opts' "
                               "signature" % (handler.__name__, co_argcount))