text: # -*- coding: utf-8 -*-
  
  from __future__ import (division, absolute_import, print_function,
                          unicode_literals)
  from six.moves import input
  #-----------------------------------------------------------------------------#
  from prompt_toolkit import PromptSession
  from prompt_toolkit.completion import Completer, Completion
  from prompt_toolkit.formatted_text import FormattedText
  from prompt_toolkit.patch_stdout import patch_stdout
  from prompt_toolkit.styles import Style
  
  from .commands import COMMANDS
  from .commands.system import INTERRUPT_CMD, NULL_CMD
  from .styles import get_style_rules
  from .utils import shlex_split
  
  ###############################################################################
  
  
  def _get_console_lexer():
      try:
          from prompt_toolkit.lexers import PygmentsLexer
          from pygments.lexers import BashLexer
      except ImportError:
          return None
      return PygmentsLexer(BashLexer)
  
  
  class CommandCompleter(Completer):
      def __init__(self, state):
          self.state = state
          self.cmd_names = sorted(k for k in COMMANDS if not k.startswith('_'))
  
      def get_completions(self, document, complete_event):
          preceding_word = document.get_word_before_cursor(WORD=True)
  
          if len(document.text) == len(preceding_word):
              # Empty or completing the first command: list commands that start
              # with the prefix
              completions = self.cmd_names
          else:
              # Process the text that's there
              args = shlex_split(document.text)
              try:
                  cmd = COMMANDS[args[0]]
              except KeyError:
                  return
  
              try:
                  get_completions = cmd.get_completions
              except AttributeError:
                  return
  
              completions = cmd.get_completions(document, args[1:], self.state)
  
          pos = -len(preceding_word)
          for arg in completions:
              if arg.startswith(preceding_word):
                  yield Completion(arg, pos)
  
  
  class Console(object):
      def __init__(self, state):
          # Command-line state
          self.state = state
          # Debug mode
          self.debug = False
          # Prompt session
          self.session = PromptSession(lexer=_get_console_lexer(),
                                       style=Style(get_style_rules()),
                                       completer=CommandCompleter(state))
          # prompt_toolkit Output class
          self.output = self.session.app.output
  
      def prompt(self):
          with patch_stdout(raw=True):
              prompt = FormattedText(self.state.get_styled_prompt(self.output))
              text = self.session.prompt(prompt)
          return text
  
      def read(self):
          """Prompt for and read a single command.
          """
          try:
              text = self.prompt()
          except KeyboardInterrupt:
              cmd = INTERRUPT_CMD.name
              args = ()
          except EOFError:
              cmd = "exit"
              args = ()
          else:
              args = shlex_split(text)
              if args:
                  cmd = args[0]
                  args = args[1:]
              else:
                  (cmd, args) = ("__NULL__", ())
          return (cmd, args)
  
      def interact(self):
          while True:
              (cmd_name, args) = self.read()
              try:
                  cmd = COMMANDS[cmd_name]
              except KeyError:
                  print("h5sh: {}: command not found".format(cmd_name))
                  continue
  
              try:
                  cmd(self.state, *args)
              except KeyboardInterrupt:
                  INTERRUPT_CMD(self.state)
              except Exception as e:
                  if not self.debug and isinstance(e, (TypeError, ValueError)):
                      print("{}: {!s}".format(cmd_name, e))
                      continue
  
                  import logging as log
                  log.exception(e)
                  continue
  