Ejemplo n.º 1
0
def _AddCliTreeKeywordsAndBuiltins(root):
    """Adds keywords and builtins to the CLI tree root."""

    # Add the exit builtin to the CLI tree.

    node = cli_tree.Node(
        command='exit',
        description='Exit the interactive shell.',
        positionals=[
            {
                'default': '0',
                'description': 'The exit status.',
                'name': 'status',
                'nargs': '?',
                'required': False,
                'value': 'STATUS',
            },
        ],
    )
    node[parser.LOOKUP_IS_GROUP] = False
    root[parser.LOOKUP_COMMANDS]['exit'] = node

    # Add special shell keywords that may be followed by commands.

    for name in [
            '!', '{', 'do', 'elif', 'else', 'if', 'then', 'time', 'until',
            'while'
    ]:
        node = cli_tree.Node(name)
        node[parser.LOOKUP_IS_GROUP] = False
        node[parser.LOOKUP_IS_SPECIAL] = True
        root[parser.LOOKUP_COMMANDS][name] = node

    # Add misc shell keywords.

    for name in ['break', 'case', 'continue', 'done', 'esac', 'fi']:
        node = cli_tree.Node(name)
        node[parser.LOOKUP_IS_GROUP] = False
        root[parser.LOOKUP_COMMANDS][name] = node
Ejemplo n.º 2
0
def LoadAll(directory=None, ignore_out_of_date=False, root=None,
            warn_on_exceptions=True):
  """Loads all CLI trees in directory and adds them to tree.

  Args:
    directory: The config directory containing the CLI tree modules.
    ignore_out_of_date: Ignore out of date trees instead of regenerating.
    root: dict, The CLI root to update. A new root is created if None.
    warn_on_exceptions: Warn on exceptions instead of raising if True.

  Raises:
    CliTreeVersionError: loaded tree version mismatch
    ImportModuleError: import errors

  Returns:
    The CLI tree.
  """
  # Create the root node if needed.
  if root is None:
    root = cli_tree.Node(description='The CLI tree root.')

  # Load the default CLI if available.
  if cli_tree.DEFAULT_CLI_NAME not in root[cli_tree.LOOKUP_COMMANDS]:
    try:
      root[cli_tree.LOOKUP_COMMANDS][cli_tree.DEFAULT_CLI_NAME] = (
          cli_tree.Load())
    except cli_tree.CliTreeLoadError:
      pass

  # Load extra CLIs by searching directories in order. .json files are treated
  # as CLI modules/data, where the file base name is the name of the CLI root
  # command.
  directories = _GetDirectories(
      directory=directory, warn_on_exceptions=warn_on_exceptions)

  loaded = {cli_tree.DEFAULT_CLI_NAME, '__init__'}  # Already loaded this above.
  for directory in directories:
    if not directory or not os.path.exists(directory):
      continue
    for (dirpath, _, filenames) in os.walk(six.text_type(directory)):
      for filename in sorted(filenames):  # For stability across runs.
        command, extension = os.path.splitext(filename)
        if extension != '.json':
          continue
        if command in loaded:
          # Already loaded. Earlier directory hits take precedence.
          continue
        loaded.add(command)
        if command == cli_tree.DEFAULT_CLI_NAME:
          tree = cli_tree.Load(os.path.join(dirpath, filename))
        else:
          tree = LoadOrGenerate(command,
                                directories=[dirpath],
                                ignore_out_of_date=ignore_out_of_date,
                                warn_on_exceptions=warn_on_exceptions)
        if tree:
          root[cli_tree.LOOKUP_COMMANDS][command] = tree
      # Don't search subdirectories.
      break

  return root
Ejemplo n.º 3
0
    def __init__(self, cosh=None, args=None, config=None):
        self.args = args
        self.coshell = cosh
        self.config = config
        self.key_bindings = bindings.KeyBindings(
            edit_mode=self.coshell.edit_mode == 'emacs')

        # Load the default CLI trees. On startup we ignore out of date trees. The
        # alternative is to regenerate them before the first prompt. This could be
        # a noticeable delay for users that accrue a lot of trees. Although ignored
        # at startup, the regen will happen on demand as the individual commands
        # are typed.
        self.root = generate_cli_trees.LoadAll(ignore_out_of_date=True,
                                               warn_on_exceptions=True)

        # Add the exit command completer node to the CLI tree.
        self.root[parser.LOOKUP_COMMANDS]['exit'] = cli_tree.Node(
            command='exit',
            description='Exit the interactive shell.',
            positionals=[
                {
                    'default': '0',
                    'description': 'The exit status.',
                    'name': 'status',
                    'nargs': '?',
                    'required': False,
                    'value': 'STATUS',
                },
            ],
        )

        # Create the parser and completer.
        interactive_parser = parser.Parser(self.root,
                                           context=config.context,
                                           hidden=config.hidden)
        interactive_completer = completer.InteractiveCliCompleter(
            interactive_parser=interactive_parser,
            args=args,
            cosh=self.coshell,
            hidden=config.hidden,
            manpage_generator=config.manpage_generator)

        # Make sure that complete_while_typing is disabled when
        # enable_history_search is enabled. (First convert to SimpleFilter, to
        # avoid doing bitwise operations on bool objects.)
        complete_while_typing = shortcuts.to_simple_filter(True)
        enable_history_search = shortcuts.to_simple_filter(False)
        complete_while_typing &= ~enable_history_search
        history_file = os.path.join(core_config.Paths().global_config_dir,
                                    'shell_history')
        multiline = shortcuts.to_simple_filter(False)

        # Create the default buffer.

        self.default_buffer = pt_buffer.Buffer(
            enable_history_search=enable_history_search,
            complete_while_typing=complete_while_typing,
            is_multiline=multiline,
            history=pt_history.FileHistory(history_file),
            validator=None,
            completer=interactive_completer,
            auto_suggest=(auto_suggest.AutoSuggestFromHistory()
                          if config.suggest else None),
            accept_action=pt_buffer.AcceptAction.RETURN_DOCUMENT,
        )

        # Create the CLI.
        self.cli = CLI(
            config=config,
            cosh=cosh,
            root=self.root,
            interactive_parser=interactive_parser,
            application=self._CreatePromptApplication(config=config,
                                                      multiline=multiline),
            eventloop=shortcuts.create_eventloop(),
            output=shortcuts.create_output(),
        )
        self.key_bindings.Initialize(self.cli)
Ejemplo n.º 4
0
  def __init__(self, cli=None, cosh=None, args=None, config=None):
    self.args = args
    self.coshell = cosh
    self.config = config
    self.key_bindings = bindings.KeyBindings(
        edit_mode=self.coshell.edit_mode == 'emacs')

    # Load the default CLI trees.
    self.root = cli_tree.LoadAll(cli=cli)

    # Add the exit command completer node to the CLI tree.
    self.root[parser.LOOKUP_COMMANDS]['exit'] = cli_tree.Node(
        command='exit',
        description='Exit the interactive shell.',
        positionals=[
            {
                'default': '0',
                'description': 'The exit status.',
                'name': 'status',
                'nargs': '?',
                'required': False,
                'value': 'STATUS',
            },
        ],
    )

    # Create the parser and completer.
    shell_parser = parser.Parser(
        self.root,
        context=config.context,
        hidden=config.hidden)
    shell_completer = completer.ShellCliCompleter(shell_parser=shell_parser,
                                                  args=args,
                                                  cosh=self.coshell,
                                                  hidden=config.hidden)

    # Make sure that complete_while_typing is disabled when
    # enable_history_search is enabled. (First convert to SimpleFilter, to
    # avoid doing bitwise operations on bool objects.)
    complete_while_typing = shortcuts.to_simple_filter(True)
    enable_history_search = shortcuts.to_simple_filter(False)
    complete_while_typing &= ~enable_history_search
    history_file = os.path.join(core_config.Paths().global_config_dir,
                                'shell_history')
    multiline = shortcuts.to_simple_filter(False)

    # Create the default buffer.

    self.default_buffer = pt_buffer.Buffer(
        enable_history_search=enable_history_search,
        complete_while_typing=complete_while_typing,
        is_multiline=multiline,
        history=pt_history.FileHistory(history_file),
        validator=None,
        completer=shell_completer,
        auto_suggest=(auto_suggest.AutoSuggestFromHistory()
                      if config.suggest else None),
        accept_action=pt_buffer.AcceptAction.RETURN_DOCUMENT,
    )

    # Create the CLI.
    self.cli = CLI(
        config=config,
        cosh=cosh,
        root=self.root,
        shell_parser=shell_parser,
        application=self._CreatePromptApplication(config=config,
                                                  multiline=multiline),
        eventloop=shortcuts.create_eventloop(),
        output=shortcuts.create_output(),
    )
    self.key_bindings.Initialize(self.cli)