docs: def start_cmd_loop(self):
          """Starts the command line loop. This method is called automatically by
             the serve_forever method. The function call is idempotent so you can
             call the method before or after that without worrying or extra
             side-effect. An EOF terminates the loop but does not close the
             server. A `KeyboardInterrupt` terminates the server as well.
          """
          # thread-safe check if the loop is already running
          with self._cmd_lock:
              cmd_start = self._cmd_start
              self._cmd_start = True
  
          if cmd_start:
              return
  
          cmd_state = {
              'suggestions': [],
              'clean_up_lock': threading.Lock(),
              'clean': False,
              'line': '',
          }
  
          # setup internal commands (no replace)
          @self.cmd(argc=0, no_replace=True)
          def help(args):  # pylint: disable=unused-variable
              msg('available commands:')
              for key in self._cmd_methods.keys():
                  msg('    {0}', key.replace('_', ' '))
  
          @self.cmd(argc=0, no_replace=True)
          def restart(args):  # pylint: disable=unused-variable
              global _do_restart
              _do_restart = True
              self.done = True
  
          @self.cmd(argc=0, no_replace=True)
          def quit(args):  # pylint: disable=unused-variable
              self.done = True
  
          # loading the history
          hfile = self.history_file
          try:
              readline.read_history_file(hfile)
          except IOError:
              pass
  
          # set up command completion
          def complete(text, state):
              if state == 0:
                  origline = readline.get_line_buffer()
                  line = origline.lstrip()
                  stripped = len(origline) - len(line)
                  begidx = readline.get_begidx() - stripped
                  endidx = readline.get_endidx() - stripped
                  prefix = line[:begidx].replace(' ', '_')
  
                  def match_cmd(cmd):
                      return cmd.startswith(prefix) and \
                             cmd[begidx:].startswith(text)
  
                  matches = filter(match_cmd, self._cmd_methods.keys())
  
                  def _endidx(m):
                      eix = m.find('_', endidx)
                      return eix + 1 if eix >= 0 else len(m)
  
                  candidates = [
                      m[begidx:_endidx(m)].replace('_', ' ') for m in matches
                  ]
                  rest_cmd = line[:begidx].split()
                  args = []
                  while rest_cmd:
                      cur_cmd = '_'.join(rest_cmd)
                      if cur_cmd in self._cmd_complete and \
                              self._cmd_complete[cur_cmd] is not None:
                          cc = self._cmd_complete[cur_cmd](args, text)
                          if cc is not None:
                              candidates.extend(cc)
                      args.insert(0, rest_cmd.pop())
                  cmd_state['suggestions'] = sorted(set(candidates))
                  cmd_state['line'] = line
              suggestions = cmd_state['suggestions']
              if len(suggestions) == 1 and text == suggestions[0]:
                  probe_cmd = cmd_state['line'].replace(' ', '_')
                  if probe_cmd in self._cmd_argc and \
                          self._cmd_argc[probe_cmd] != 0:
                      cmd_state['line'] = ""
                      return text + ' '
                  return None
              if state < len(suggestions):
                  return suggestions[state]
              return None
  
          old_completer = readline.get_completer()
          readline.set_completer(complete)
          # be mac compatible
          if readline.__doc__ is not None and 'libedit' in readline.__doc__:
              readline.parse_and_bind("bind ^I rl_complete")
          else:
              readline.parse_and_bind("tab: complete")
  
          # remember to clean up before exit -- the call must be idempotent!
          def clean_up():
              with cmd_state['clean_up_lock']:
                  clean = cmd_state['clean']
                  cmd_state['clean'] = True
  
              if clean:
                  return
  
              readline.write_history_file(hfile)
              readline.set_completer(old_completer)
          atexit.register(clean_up)
          self._clean_up_call = clean_up
  
          def cmd_loop():
              close = False
              kill = True
              try:
                  while not self.done and not close and not self.no_command_loop:
                      line = ""
                      try:
                          try:
                              line = input(self.prompt)
                          except IOError as e:
                              if e.errno == errno.EBADF:
                                  close = True
                                  kill = False
                              elif (e.errno == errno.EWOULDBLOCK or
                                    e.errno == errno.EAGAIN or
                                    e.errno == errno.EINTR):
                                  continue
                              else:
                                  raise e
                          self.handle_cmd(line)
                      except EOFError:
                          close = True
                          kill = False
                      except KeyboardInterrupt:
                          close = True
                      except Exception:
                          msg("{0}", traceback.format_exc())
                          msg("^ exception executing command {0} ^", line)
              finally:
                  if kill:
                      self.done = True
                  else:
                      msg("no command loop - use CTRL-C to terminate")
                      self.no_command_loop = True
                  clean_up()
  
          if not self.no_command_loop:
              t = self._thread_factory(target=cmd_loop)
              t.daemon = True
              t.start()