Beispiel #1
0
def prompt(
    message: str,
    rprompt: Optional[str] = None,
    validator: Optional[Validator] = None,
    default: str = "",
) -> Optional[str]:
    bindings = key_binding.KeyBindings()

    bindings.add("escape", eager=True)(handle_escape)

    right_side_prompt = "ESC to go back"

    if rprompt:
        right_side_prompt = "{0} | {1}".format(right_side_prompt, rprompt)

    return cast(
        Optional[str],
        toolkit_prompt(
            HTML(message),
            key_bindings=bindings,
            rprompt=right_side_prompt,
            validator=validator,
            default=default,
            validate_while_typing=False,
        ),
    )
Beispiel #2
0
    def build_propmpt(self) -> pt_shortcuts.PromptSession:
        history = pt_history.FileHistory(
            os.path.expanduser('~/.edgedbhistory'))

        bindings = pt_key_binding.KeyBindings()
        handle = bindings.add

        @handle('f3')  # type: ignore
        def _mode_toggle(event: Any) -> None:
            self.context.toggle_query_mode()

        @handle('f4')  # type: ignore
        def _implicit_toggle(event: Any) -> None:
            self.context.toggle_implicit()

        @handle('f5')  # type: ignore
        def _introspect_toggle(event: Any) -> None:
            self.context.toggle_introspect_types()

            if self.context.introspect_types:
                self.ensure_connection()
                self.introspect_db(self.connection)
            else:
                self.context.typenames = None

        @handle('tab')  # type: ignore
        def _tab(event: Any) -> None:
            b = prompt.app.current_buffer
            before_cursor = b.document.current_line_before_cursor
            if b.text and (not before_cursor or before_cursor.isspace()):
                b.insert_text('    ')

        prompt = pt_shortcuts.PromptSession(
            lexer=pt_lexers.PygmentsLexer(eql_pygments.EdgeQLLexer),
            include_default_pygments_style=False,

            completer=pt_complete.DummyCompleter(),
            reserve_space_for_menu=6,

            message=self.get_prompt_tokens,
            prompt_continuation=self.get_continuation_tokens,
            bottom_toolbar=self.get_toolbar_tokens,
            multiline=is_multiline,
            history=history,
            complete_while_typing=pt_filters.Always(),
            key_bindings=bindings,
            style=self.style,
            editing_mode=pt_enums.EditingMode.VI,
            search_ignore_case=True,
        )

        return prompt
Beispiel #3
0
def override_key_binding(**kwargs):
    kb = key_binding.KeyBindings()

    @kb.add("backspace")
    def _backspace(event) -> None:
        # Normal backspace event
        named_commands.backward_delete_char(event)
        # Empty string is inserted to invoke completer
        event.current_buffer.insert_text("")

    @kb.add("c-d")
    def _quit_interactive(event) -> None:
        # Quit Interactive CLI when user presses [CTRL + D]
        get_app().exit()

    @kb.add("enter")
    def _enter_key(event) -> None:
        # the main purpose of this function is, pressing enter chooses the option then pressing enter again executes the
        # command
        buffer = event.current_buffer
        missing_required_param = all_required_param_selected(
            buffer.text, kwargs["completer"].list_of_required_params
        )
        if (
            not buffer.text or not buffer.complete_state
        ):  # If in the beginning or no menu(meaning menu is already chosen)
            if not missing_required_param:
                named_commands.accept_line(event)
            else:
                kwargs["toolbar"].set_toolbar_text(
                    get_error_message(
                        "missing_required_params", str(missing_required_param)
                    ),
                    is_error=True,
                )
        else:  # Copy the current selection and append it a new document
            document_with_selection, _ = buffer.document.cut_selection()
            buffer.reset()
            buffer.document = document_with_selection

    @kb.add("f7")
    def _clear_history(event) -> None:
        buffer = event.current_buffer

        # Clear history when user presses [F7] shortcut keys
        try:
            # Clear Command History
            cli_interactive_history = buffer.history
            cli_interactive_history.delete_history_file()

            # Clear Cache
            buffer.reset()

        # Notify User
        except Exception as e:
            kwargs["toolbar"].set_toolbar_text(
                get_error_message("try_again"),
                is_error=True,
            )
        else:
            kwargs["toolbar"].set_toolbar_text(
                get_error_message("history_clear"),
                is_error=False,
            )

    return kb
Beispiel #4
0
  def __init__(
      self,
      switchboard_inst: switchboard_base.SwitchboardBase,
      device_log_file_name: str,
      configuration: console_config.ConsoleConfiguration,
      console_input: Optional[prompt_toolkit_input.Input] = None,
      console_output: Optional[output.Output] = None) -> None:
    """Initializes a prompt_toolkit console application.

    Args:
      switchboard_inst: Switchboard capability instance.
      device_log_file_name: The device log file to read (stream) logs from.
      configuration: Console configuration.
      console_input: Console input. Defaults to stdin.
      console_output: Console output. Defaults to stdout.
    """
    self._device_log_file_name = device_log_file_name
    self._window_line_transforms = configuration.window_line_transforms
    self._line_to_window_id = configuration.line_to_window_id
    self._log_file = None  # Set by run().

    body_frames = []
    self._window_id_to_text_area = collections.OrderedDict()
    for window in configuration.windows:
      text_area, enclosing_frame = _make_ui_window(window, switchboard_inst)
      self._window_id_to_text_area[window.window_id] = text_area
      body_frames.append(enclosing_frame)

    self._menu_exit_item = widgets.MenuItem("Exit", handler=_do_exit)
    if body_frames:
      self._default_focused_element = body_frames[0]
    else:
      self._default_focused_element = self._menu_exit_item
    help_window_visibility = _HelpWindowVisibility(
        focus_element_on_hide=self._default_focused_element)
    close_help_button = widgets.Button(
        text="Ok",
        handler=help_window_visibility.hide)
    help_window_visibility.focus_element_on_show = close_help_button
    help_float_dialog = containers.Float(
        containers.ConditionalContainer(
            content=widgets.Dialog(
                title="Console help",
                body=widgets.TextArea(
                    text=_HELP_TEXT,
                    focusable=True,
                    read_only=True,
                    scrollbar=True,
                    width=_HELP_TEXT_WIDTH,
                ),
                buttons=[close_help_button],
            ),
            filter=filters.Condition(help_window_visibility.is_visible),
        ),
    )

    root_container = widgets.MenuContainer(
        body=containers.FloatContainer(
            content=containers.HSplit(body_frames),
            floats=[help_float_dialog],
        ),
        menu_items=[
            self._menu_exit_item,
            widgets.MenuItem("Help", handler=help_window_visibility.show),
        ],
    )

    button_list = switchboard_inst.button_list
    button_names = button_list[0].valid_buttons() if button_list else []
    if button_names:
      button_menu_items = [
          _make_button_menu_item(button_name, switchboard_inst, root_container)
          for button_name in button_names
      ]
      self._button_dropdown = widgets.MenuItem(
          "Buttons", children=button_menu_items)
      root_container.menu_items.append(self._button_dropdown)
    else:
      self._button_dropdown = None

    # Global key bindings.
    bindings = key_binding.KeyBindings()
    bindings.add("tab")(focus.focus_next)
    bindings.add("s-tab")(focus.focus_previous)

    style = styles.Style.from_dict({
        "menu-bar": "bg:#aaaaaa #888888",
    })

    self._application = application.Application(
        layout=layout.Layout(
            container=root_container,
            focused_element=self._default_focused_element,
        ),
        style=style,
        full_screen=True,
        key_bindings=bindings,
        editing_mode=enums.EditingMode.VI,
        input=console_input,
        output=console_output,
    )
Beispiel #5
0
def _make_ui_window(
    window: console_config.WindowType,
    switchboard_inst: switchboard_base.SwitchboardBase
) -> Tuple[widgets.TextArea, widgets.Frame]:
  """Creates a text area and an enclosing frame.

  Args:
    window: Console window description.
    switchboard_inst: Switchboard capability instance.

  Returns:
    A tuple containing the window's text area and its enclosing UI frame.
  """
  if isinstance(window, console_config.CommandInputWindow):

    def handle_command_input(input_buffer: buffer.Buffer) -> None:
      command = input_buffer.text
      switchboard_inst.send(command, port=window.transport)

    command_input_area = widgets.TextArea(
        text="",
        multiline=False,
        accept_handler=handle_command_input,
        history=None,
        focusable=True,
        read_only=False,
        get_line_prefix=lambda line_num, wrap_count: " > "
    )
    command_input_area_bindings = key_binding.KeyBindings()

    @command_input_area_bindings.add("c-c")
    def _handle_control_c(event) -> None:  # pylint: disable=unused-variable
      del event  # Unused.
      command_input_area.text = ""
      if window.reopen_transport_on_ctrl_c:
        switchboard_inst.add_log_note(
            "The transport is running in non-interactive mode. "
            "Ctrl-C keystrokes are ignored by the device. "
            "Reopening the command transport as a workaround. "
            "Shell environment variables will be lost.")
        switchboard_inst.close_transport(port=window.transport)
        switchboard_inst.open_transport(port=window.transport)
      else:
        switchboard_inst.send(b"\x03", port=window.transport)

    command_input_area.control.key_bindings = command_input_area_bindings
    command_input_frame = widgets.Frame(
        body=command_input_area,
        title=window.name)
    return command_input_area, command_input_frame

  else:  # CommandResponseWindow or LogWindow
    search_toolbar = widgets.SearchToolbar()
    text_area = _AppendableTextArea(
        text="",
        focusable=True,
        read_only=True,
        line_numbers=True,
        scrollbar=True,
        search_field=search_toolbar,
    )
    text_area.window.ignore_content_height = lambda: True
    frame = widgets.Frame(
        body=containers.HSplit([
            text_area,
            search_toolbar,
        ]),
        title=window.name)
    return text_area, frame
Beispiel #6
0
from contextlib import suppress
from typing import Optional

from prompt_toolkit import completion, key_binding, prompt
from prompt_toolkit.filters import completion_is_selected, has_completions

from huntinghorn.constants import horns
from huntinghorn.utils import Horn


key_bindings = key_binding.KeyBindings()
completer = completion.FuzzyWordCompleter(horns.keys())


@key_bindings.add("enter", filter=has_completions & ~completion_is_selected)
def validate_text(event: key_binding.key_processor.KeyPressEvent) -> None:
    """Validate the current selection once enter is pressed."""
    event.current_buffer.go_to_completion(0)
    event.current_buffer.validate_and_handle()


def prompt_for_horn() -> Optional[Horn]:
    """Prompt the user to select a Horn."""
    with suppress(KeyboardInterrupt):
        name = str(prompt(
            "Horn: ",
            completer=completer,
            complete_while_typing=True,
            key_bindings=key_bindings,
        ))
        print()