Example #1
0
    def pt_init(self):
        def get_prompt_tokens():
            return [(Token.Prompt, self.prompt)]

        if self._ptcomp is None:
            compl = IPCompleter(shell=self.shell,
                                        namespace={},
                                        global_namespace={},
                                        parent=self.shell,
                                       )
            self._ptcomp = IPythonPTCompleter(compl)

        kb = KeyBindings()
        supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
        kb.add('c-z', filter=supports_suspend)(suspend_to_bg)

        if self.shell.display_completions == 'readlinelike':
            kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
                                  & ~has_selection
                                  & vi_insert_mode | emacs_insert_mode
                                  & ~cursor_in_leading_ws
                              ))(display_completions_like_readline)

        self.pt_app = PromptSession(
                            message=(lambda: PygmentsTokens(get_prompt_tokens())),
                            editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
                            key_bindings=kb,
                            history=self.shell.debugger_history,
                            completer=self._ptcomp,
                            enable_history_search=True,
                            mouse_support=self.shell.mouse_support,
                            complete_style=self.shell.pt_complete_style,
                            style=self.shell.style,
                            inputhook=self.shell.inputhook,
        )
Example #2
0
    def __init__(self, player):
        self.player = player
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
                ('', ' '),
                ('#cc00cc', self.playerClans, "utf-8"),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
            ]) 
        self.result = None

        self.mainRadiosRows = []
        self.listOfItems = []
        self.populateMainRadios() # declares self.mainRadios
        self.currentRadios = self.mainRadios
        self.description = self.mainRadios.description # description is whataver is in the description box on the right
        self.requestingConfirmation = False
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.handleEscape)

        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getRootContainer(),
                focused_element=self.mainRadios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )
Example #3
0
    def __init__(self, pymux):
        self.pymux = pymux

        def get_search_state():
            " Return the currently active SearchState. (The one for the focused pane.) "
            return pymux.arrangement.get_active_pane().search_state

        self.custom_key_bindings = KeyBindings()

        self.key_bindings = merge_key_bindings([
            self._load_builtins(),
            self.custom_key_bindings,
        ])

        self._prefix = ('c-b', )
        self._prefix_binding = None

        # Load initial bindings.
        self._load_prefix_binding()

        # Custom user configured key bindings.
        # { (needs_prefix, key) -> (command, handler) }
        self.custom_bindings = {}
Example #4
0
    def bindings(self):
        bindings = KeyBindings()
        bindings.add('c-c')(self.do_exit)
        bindings.add('i')(self.action(self.server_windows[0].content.set_payload_key, "indexes"))
        bindings.add('m')(self.action(self.server_windows[0].content.set_payload_key, "metaData"))
        bindings.add('p')(self.action(self.server_windows[0].content.set_payload_key, "parameters"))
        bindings.add('q')(self.action(self.server_windows[0].content.set_payload_key, "query"))

        bindings.add('f12')(self.toggle_overview)
        bindings.add('c-o')(self.toggle_overview)
        bindings.add('insert')(self.action(self.insert))
        bindings.add('+')(self.action(self.insert))
        bindings.add('delete')(self.action(self.delete))
        bindings.add('-')(self.action(self.delete))
        bindings.add('home')(self.action(self.overview.home))
        bindings.add('end')(self.action(self.overview.end))
        bindings.add('pageup')(self.action(self.overview.page_up))
        bindings.add('pagedown')(self.action(self.overview.page_down))

        return bindings
Example #5
0
def create_keybindings(app: Application) -> KeyBindings:
    keys_info = get_keys_info()
    kb = KeyBindings()

    @kb.add(
        'escape',  # type: ignore
        filter=Condition(lambda: app.message_toolbar.text))
    def _(event: Event) -> None:
        event.app.message_toolbar.text = None

    @kb.add(
        'escape',  # type: ignore
        filter=Condition(lambda: app.error_toolbar.text))
    def _escape(event: Event) -> None:
        event.app.error_toolbar.text = None

    @kb.add('c-n', filter=~has_focus(app.info_window))  # type: ignore
    @kb.add(
        keys_info["move_down_key"]["key"],  # type: ignore
        filter=~has_focus(app.info_window))
    def down_(event: Event) -> None:
        event.app.options_list.move_down()
        event.app.refresh()
        event.app.update()

    @kb.add(  # type: ignore
        keys_info["move_down_while_info_window_active_key"]["key"],
        filter=has_focus(app.info_window))
    def down_info(event: Event) -> None:
        down_(event)
        event.app.update_info_window()

    @kb.add('c-p', filter=~has_focus(app.info_window))  # type: ignore
    @kb.add(
        keys_info["move_up_key"]["key"],  # type: ignore
        filter=~has_focus(app.info_window))
    def up_(event: Event) -> None:
        event.app.options_list.move_up()
        event.app.refresh()
        event.app.update()

    @kb.add(  # type: ignore
        keys_info["move_up_while_info_window_active_key"]["key"],
        filter=has_focus(app.info_window))
    def up_info(event: Event) -> None:
        up_(event)
        event.app.update_info_window()

    @kb.add('q', filter=has_focus(app.help_window))  # type: ignore
    @kb.add('escape', filter=has_focus(app.help_window))  # type: ignore
    def _help_quit(event: Event) -> None:
        event.app.layout.focus(app.help_window.window)
        event.app.layout.focus(app.command_line_prompt.window)
        event.app.message_toolbar.text = None
        event.app.layout.focus(event.app.options_list.search_buffer)

    @kb.add('q', filter=has_focus(app.info_window))  # type: ignore
    @kb.add('s-tab', filter=has_focus(app.info_window))  # type: ignore
    @kb.add('escape', filter=has_focus(app.info_window))  # type: ignore
    def _info(event: Event) -> None:
        event.app.layout.focus(event.app.options_list.search_buffer)
        event.app.message_toolbar.text = None

    @kb.add(
        keys_info["focus_command_line_key"]["key"],  # type: ignore
        filter=~has_focus(app.command_line_prompt))
    def _command_window(event: Event) -> None:
        event.app.layout.focus(app.command_line_prompt.window)

    @kb.add('enter', filter=has_focus(app.command_line_prompt))  # type: ignore
    def _enter_(event: Event) -> None:
        event.app.layout.focus(event.app.options_list.search_buffer)
        try:
            event.app.command_line_prompt.trigger()
        except Exception as e:
            event.app.error_toolbar.text = str(e)
        event.app.command_line_prompt.clear()

    @kb.add(
        'escape',  # type: ignore
        filter=has_focus(app.command_line_prompt))
    def _escape_when_commandline_has_focus(event: Event) -> None:
        event.app.layout.focus(event.app.options_list.search_buffer)
        event.app.command_line_prompt.clear()

    @kb.add('c-t')  # type: ignore
    def _toggle_mark_(event: Event) -> None:
        event.app.options_list.toggle_mark_current_selection()

    return kb
Example #6
0
from prompt_toolkit.key_binding import KeyBindings
from ui.DisplayContainer import display_container, AlarmThread, buffer
from dialog.SetAlarmDialog import SetAlarmDialog

kb = KeyBindings()


@kb.add('c-q')
def exit_(event):
    '''
    退出快捷键
    :param event: 事件内容
    :return: null
    '''
    display_container.alarm_thread.stop()
    event.app.exit()


@kb.add('c-w')
def stop_(event):
    '''
    停止计时快捷键
    :param event: 事件内容
    :return:null
    '''
    display_container.alarm_thread.stop()


@kb.add('c-s')
def start_(event):
    '''
Example #7
0
    HSplit([
        Label(text="Press `Tab` to move the focus."),
        HSplit([
            VSplit(
                [btn_start, btn_pause, btn_reset, btn_reset_all, btn_exit],
                padding=1,
                style="bg:#cccccc",
            ),
            text_area,
        ]),
    ]))

layout = Layout(container=root_container, focused_element=btn_start)

# Key bindings.
kb = KeyBindings()
kb.add("tab")(focus_next)
kb.add("s-tab")(focus_previous)
kb.add("right")(focus_next)
kb.add("left")(focus_previous)
kb.add("q")(exit_clicked)

# Styling.
style = Style([
    ("left-pane", "bg:#888800 #000000"),
    ("right-pane", "bg:#00aa00 #000000"),
    ("button", "#000000"),
    ("button-arrow", "#000000"),
    ("button focused", "bg:#ff0000"),
    ("text-area", "bg:#ffffff #000000"),
    ("red", "#ff0000"),
Example #8
0
def cli_bindings(cli):
    """
    Custom key bindings for cli.
    """
    kb = KeyBindings()

    @kb.add('f2')
    def _(event):
        """
        Enable/Disable SmartCompletion Mode.
        """
        _logger.debug('Detected F2 key.')
        cli.completer.start_completion = not cli.completer.start_completion

    @kb.add('f3')
    def _(event):
        """
        Enable/Disable Multiline Mode.
        """
        _logger.debug('Detected F3 key.')
        cli.multi_line = not cli.multi_line

    @kb.add('f4')
    def _(event):
        """
        Toggle between Vi and Emacs mode.
        """
        _logger.debug('Detected F4 key.')
        if cli.key_bindings == 'vi':
            event.app.editing_mode = EditingMode.EMACS
            cli.key_bindings = 'emacs'
        else:
            event.app.editing_mode = EditingMode.VI
            cli.key_bindings = 'vi'

    @kb.add('tab')
    def _(event):
        """
        Force autocompletion at cursor.
        """
        _logger.debug('Detected <Tab> key.')
        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=True)

    @kb.add('c-space')
    def _(event):
        """
        Initialize autocompletion at cursor.
        If the autocompletion menu is not showing, display it with the
        appropriate completions for the context.
        If the menu is showing, select the next completion.
        """
        _logger.debug('Detected <C-Space> key.')

        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=False)

    @kb.add('enter', filter=completion_is_selected)
    def _(event):
        """
        Makes the enter key work as the tab key only when showing the menu.
        """
        _logger.debug('Detected enter key.')

        event.current_buffer.complete_state = None
        b = event.app.current_buffer
        b.complete_state = None

    return kb
Example #9
0
    def __init__(
        self,
        get_globals: Optional[_GetNamespace] = None,
        get_locals: Optional[_GetNamespace] = None,
        history_filename: Optional[str] = None,
        vi_mode: bool = False,
        color_depth: Optional[ColorDepth] = None,
        # Input/output.
        input: Optional[Input] = None,
        output: Optional[Output] = None,
        # For internal use.
        extra_key_bindings: Optional[KeyBindings] = None,
        _completer: Optional[Completer] = None,
        _validator: Optional[Validator] = None,
        _lexer: Optional[Lexer] = None,
        _extra_buffer_processors=None,
        _extra_layout_body=None,
        _extra_toolbars=None,
        _input_buffer_height=None,
    ) -> None:

        self.get_globals: _GetNamespace = get_globals or (lambda: {})
        self.get_locals: _GetNamespace = get_locals or self.get_globals

        self._completer = HidePrivateCompleter(
            _completer or FuzzyCompleter(
                PythonCompleter(
                    self.get_globals,
                    self.get_locals,
                    lambda: self.enable_dictionary_completion,
                ),
                enable_fuzzy=Condition(lambda: self.enable_fuzzy_completion),
            ),
            lambda: self.complete_private_attributes,
        )
        self._validator = _validator or PythonValidator(
            self.get_compiler_flags)
        self._lexer = _lexer or PygmentsLexer(PythonLexer)

        self.history: History
        if history_filename:
            self.history = ThreadedHistory(FileHistory(history_filename))
        else:
            self.history = InMemoryHistory()

        self._input_buffer_height = _input_buffer_height
        self._extra_layout_body = _extra_layout_body or []
        self._extra_toolbars = _extra_toolbars or []
        self._extra_buffer_processors = _extra_buffer_processors or []

        self.extra_key_bindings = extra_key_bindings or KeyBindings()

        # Settings.
        self.title: AnyFormattedText = ""
        self.show_signature: bool = False
        self.show_docstring: bool = False
        self.show_meta_enter_message: bool = True
        self.completion_visualisation: CompletionVisualisation = (
            CompletionVisualisation.MULTI_COLUMN)
        self.completion_menu_scroll_offset: int = 1

        self.show_line_numbers: bool = False
        self.show_status_bar: bool = True
        self.wrap_lines: bool = True
        self.complete_while_typing: bool = True
        self.paste_mode: bool = (
            False  # When True, don't insert whitespace after newline.
        )
        self.confirm_exit: bool = (
            True  # Ask for confirmation when Control-D is pressed.
        )
        self.accept_input_on_enter: int = 2  # Accept when pressing Enter 'n' times.
        # 'None' means that meta-enter is always required.
        self.enable_open_in_editor: bool = True
        self.enable_system_bindings: bool = True
        self.enable_input_validation: bool = True
        self.enable_auto_suggest: bool = False
        self.enable_mouse_support: bool = False
        self.enable_history_search: bool = False  # When True, like readline, going
        # back in history will filter the
        # history on the records starting
        # with the current input.

        self.enable_syntax_highlighting: bool = True
        self.enable_fuzzy_completion: bool = False
        self.enable_dictionary_completion: bool = False
        self.complete_private_attributes: CompletePrivateAttributes = (
            CompletePrivateAttributes.ALWAYS)
        self.swap_light_and_dark: bool = False
        self.highlight_matching_parenthesis: bool = False
        self.show_sidebar: bool = False  # Currently show the sidebar.

        # When the sidebar is visible, also show the help text.
        self.show_sidebar_help: bool = True

        # Currently show 'Do you really want to exit?'
        self.show_exit_confirmation: bool = False

        # The title to be displayed in the terminal. (None or string.)
        self.terminal_title: Optional[str] = None

        self.exit_message: str = "Do you really want to exit?"
        self.insert_blank_line_after_output: bool = True  # (For the REPL.)
        self.insert_blank_line_after_input: bool = False  # (For the REPL.)

        # The buffers.
        self.default_buffer = self._create_buffer()
        self.search_buffer: Buffer = Buffer()
        self.docstring_buffer: Buffer = Buffer(read_only=True)

        # Tokens to be shown at the prompt.
        self.prompt_style: str = "classic"  # The currently active style.

        # Styles selectable from the menu.
        self.all_prompt_styles: Dict[str, PromptStyle] = {
            "ipython": IPythonPrompt(self),
            "classic": ClassicPrompt(),
        }

        self.get_input_prompt = lambda: self.all_prompt_styles[
            self.prompt_style].in_prompt()

        self.get_output_prompt = lambda: self.all_prompt_styles[
            self.prompt_style].out_prompt()

        #: Load styles.
        self.code_styles: Dict[str, BaseStyle] = get_all_code_styles()
        self.ui_styles = get_all_ui_styles()
        self._current_code_style_name: str = "default"
        self._current_ui_style_name: str = "default"

        if is_windows():
            self._current_code_style_name = "win32"

        self._current_style = self._generate_style()
        self.color_depth: ColorDepth = color_depth or ColorDepth.default()

        self.max_brightness: float = 1.0
        self.min_brightness: float = 0.0

        # Options to be configurable from the sidebar.
        self.options = self._create_options()
        self.selected_option_index: int = 0

        #: Incremeting integer counting the current statement.
        self.current_statement_index: int = 1

        # Code signatures. (This is set asynchronously after a timeout.)
        self.signatures: List[Any] = []

        # Boolean indicating whether we have a signatures thread running.
        # (Never run more than one at the same time.)
        self._get_signatures_thread_running: bool = False

        # Get into Vi navigation mode at startup
        self.vi_start_in_navigation_mode: bool = False

        # Preserve last used Vi input mode between main loop iterations
        self.vi_keep_last_used_mode: bool = False

        self.style_transformation = merge_style_transformations([
            ConditionalStyleTransformation(
                SwapLightAndDarkStyleTransformation(),
                filter=Condition(lambda: self.swap_light_and_dark),
            ),
            AdjustBrightnessStyleTransformation(lambda: self.min_brightness,
                                                lambda: self.max_brightness),
        ])
        self.ptpython_layout = PtPythonLayout(
            self,
            lexer=DynamicLexer(lambda: self._lexer if self.
                               enable_syntax_highlighting else SimpleLexer()),
            input_buffer_height=self._input_buffer_height,
            extra_buffer_processors=self._extra_buffer_processors,
            extra_body=self._extra_layout_body,
            extra_toolbars=self._extra_toolbars,
        )

        self.app = self._create_application(input, output)

        if vi_mode:
            self.app.editing_mode = EditingMode.VI
Example #10
0
def select(
    message: str,
    choices: Sequence[Union[str, Choice, Dict[str, Any]]],
    default: Optional[Union[str, Choice, Dict[str, Any]]] = None,
    qmark: str = DEFAULT_QUESTION_PREFIX,
    pointer: Optional[str] = DEFAULT_SELECTED_POINTER,
    style: Optional[Style] = None,
    use_shortcuts: bool = False,
    use_arrow_keys: bool = True,
    use_indicator: bool = False,
    instruction: Optional[str] = None,
    **kwargs: Any,
) -> Question:
    """A list of items to select **one** option from.

    The user can pick one option and confirm it (if you want to allow
    the user to select multiple options, use :meth:`questionary.checkbox` instead).

    Example:
        >>> import questionary
        >>> questionary.select(
        ...     "What do you want to do?",
        ...     choices=[
        ...         "Order a pizza",
        ...         "Make a reservation",
        ...         "Ask for opening hours"
        ...     ]).ask()
        ? What do you want to do? Order a pizza
        'Order a pizza'

    .. image:: ../images/select.gif

    This is just a realy basic example, the prompt can be customised using the
    parameters.


    Args:
        message: Question text

        choices: Items shown in the selection, this can contain :class:`Choice` or
                 or :class:`Separator` objects or simple items as strings. Passing
                 :class:`Choice` objects, allows you to configure the item more
                 (e.g. preselecting it or disabling it).

        default: A value corresponding to a selectable item in the choices,
                 to initially set the pointer position to.

        qmark: Question prefix displayed in front of the question.
               By default this is a ``?``.

        pointer: Pointer symbol in front of the currently highlighted element.
                 By default this is a ``»``.
                 Use ``None`` to disable it.

        instruction: A hint on how to navigate the menu.
                     It's ``(Use shortcuts)`` if only ``use_shortcuts`` is set
                     to True, ``(Use arrow keys or shortcuts)`` if ``use_arrow_keys``
                     & ``use_shortcuts`` are set and ``(Use arrow keys)`` by default.

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

        use_indicator: Flag to enable the small indicator in front of the
                       list highlighting the current location of the selection
                       cursor.

        use_shortcuts: Allow the user to select items from the list using
                       shortcuts. The shortcuts will be displayed in front of
                       the list items.

        use_arrow_keys: Allow usage of arrow keys to select item.

    Returns:
        :class:`Question`: Question instance, ready to be prompted (using ``.ask()``).
    """
    if choices is None or len(choices) == 0:
        raise ValueError("A list of choices needs to be provided.")

    if use_shortcuts and len(choices) > len(InquirerControl.SHORTCUT_KEYS):
        raise ValueError("A list with shortcuts supports a maximum of {} "
                         "choices as this is the maximum number "
                         "of keyboard shortcuts that are available. You"
                         "provided {} choices!"
                         "".format(len(InquirerControl.SHORTCUT_KEYS),
                                   len(choices)))

    merged_style = merge_styles([DEFAULT_STYLE, style])

    ic = InquirerControl(
        choices,
        default,
        pointer=pointer,
        use_indicator=use_indicator,
        use_shortcuts=use_shortcuts,
        use_arrow_keys=use_arrow_keys,
        initial_choice=default,
    )

    def get_prompt_tokens():
        # noinspection PyListCreation
        tokens = [("class:qmark", qmark),
                  ("class:question", " {} ".format(message))]

        if ic.is_answered:
            if isinstance(ic.get_pointed_at().title, list):
                tokens.append((
                    "class:answer",
                    "".join([token[1] for token in ic.get_pointed_at().title]),
                ))
            else:
                tokens.append(("class:answer", ic.get_pointed_at().title))
        else:
            if instruction:
                tokens.append(("class:instruction", instruction))
            else:
                if use_shortcuts and use_arrow_keys:
                    instruction_msg = "(Use shortcuts or arrow keys)"
                elif use_shortcuts and not use_arrow_keys:
                    instruction_msg = "(Use shortcuts)"
                else:
                    instruction_msg = "(Use arrow keys)"
                tokens.append(("class:instruction", instruction_msg))

        return tokens

    layout = common.create_inquirer_layout(ic, get_prompt_tokens, **kwargs)

    bindings = KeyBindings()

    @bindings.add(Keys.ControlQ, eager=True)
    @bindings.add(Keys.ControlC, eager=True)
    def _(event):
        event.app.exit(exception=KeyboardInterrupt, style="class:aborting")

    if use_shortcuts:
        # add key bindings for choices
        for i, c in enumerate(ic.choices):
            if isinstance(c, Separator):
                continue

            # noinspection PyShadowingNames
            def _reg_binding(i, keys):
                # trick out late evaluation with a "function factory":
                # https://stackoverflow.com/a/3431699
                @bindings.add(keys, eager=True)
                def select_choice(event):
                    ic.pointed_at = i

            _reg_binding(i, c.shortcut_key)

    if use_arrow_keys or use_shortcuts is False:

        @bindings.add(Keys.Down, eager=True)
        @bindings.add("j", eager=True)
        def move_cursor_down(event):
            ic.select_next()
            while not ic.is_selection_valid():
                ic.select_next()

        @bindings.add(Keys.Up, eager=True)
        @bindings.add("k", eager=True)
        def move_cursor_up(event):
            ic.select_previous()
            while not ic.is_selection_valid():
                ic.select_previous()

    @bindings.add(Keys.ControlM, eager=True)
    def set_answer(event):
        ic.is_answered = True
        event.app.exit(result=ic.get_pointed_at().value)

    @bindings.add(Keys.Any)
    def other(event):
        """Disallow inserting other text. """
        pass

    return Question(
        Application(
            layout=layout,
            key_bindings=bindings,
            style=merged_style,
            **utils.used_kwargs(kwargs, Application.__init__),
        ))
Example #11
0
File: helpers.py Project: ghcdr/uhu
from prompt_toolkit.filters import HasCompletions
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys

from ..core.validators import validate_option_requirements
from ..core.object import Modes
from ..core._options import Options

from .completers import (ObjectFilenameCompleter, ObjectModeCompleter,
                         ObjectOptionValueCompleter, ObjectUIDCompleter,
                         YesNoCompleter)
from .exceptions import CancelPromptException
from .validators import (ObjectUIDValidator, ContainerValidator,
                         ObjectOptionValueValidator, PackageUIDValidator)

registry = KeyBindings()  # pylint: disable=invalid-name


@registry.add(Keys.ControlD)
def ctrl_d(_):
    """Ctrl D quits appliaction returning 0 to sys."""
    sys.exit(0)


@registry.add(Keys.ControlC)
def ctrl_c(_):
    """Ctrl C raises an exception to be caught by functions.

    Main prompt must exit uhu with code status 1, while subprompts
    must returns to main prompt.
    """
Example #12
0
def main(debug, data_path, username, role, host_ip, redis_port, ftp_port):

    ftpText = '===============================\n              ftp              \n===============================\n'
    dashboardText = '===============================\n           Dashboard           \n===============================\n'
    exploitText = '===============================\n            Exploit            \n===============================\n'
    defenseText = '===============================\n            Defense            \n===============================\n'
    analysisText = '===============================\n           Analysis            \n===============================\n'

    ftp_field = TextArea(text=ftpText, height=10)
    dashboard_field = TextArea(text=dashboardText)
    exploit_field = TextArea(text=exploitText)
    defense_field = TextArea(text=defenseText)
    analysis_field = TextArea(text=analysisText)

    input_field = TextArea(height=1,
                           prompt=' > ',
                           style='class:input-field',
                           completer=PathCompleter())

    global user, redis, ftp, dashboard
    user = User(username, role, dashboard_field)
    redis = RedisManager(ip=host_ip,
                         port=redis_port,
                         printField=dashboard_field,
                         user=user,
                         debug=debug)
    ftp = FTPHandler(ip=host_ip,
                     port=ftp_port,
                     path=data_path + 'ftp/',
                     user=user,
                     printField=ftp_field)

    analysis = Analysis(redis, None, ftp, [dashboard_field, analysis_field])
    exploit = Exploit(redis, None, ftp, [dashboard_field, exploit_field])
    dashboard = Dashboard(redis,
                          exploit,
                          None,
                          analysis,
                          dashboard_field,
                          debug=debug)

    if user.getRole() == 'None':
        leftSplit = HSplit([
            ftp_field,
            Window(height=1, char='-', style='class:line'), dashboard_field
        ])
    else:
        leftSplit = dashboard_field

    container = HSplit([
        VSplit([
            leftSplit,
            Window(width=1, char='|', style='class:line'),
            HSplit([
                exploit_field,
                Window(height=1, char='-', style='class:line'), defense_field,
                Window(height=1, char='-', style='class:line'), analysis_field
            ])
        ]),
        Window(height=1, char='-', style='class:line'), input_field
    ])

    kb = KeyBindings()

    @kb.add('c-q')
    def _(event):
        event.app.exit()

    @kb.add('c-c')
    def _(event):
        input_field.text = ''

    @kb.add('c-o')
    def _(event):
        global select
        if 'Exploit' in select:
            exploit.process(select, 'help')
        elif 'Defense' in select:
            pass
        elif 'Analysis' in select:
            analysis.process(select, 'help')
        else:
            dashboard.process(select, 'help')

    @kb.add('enter')
    def _(event):
        global stopSignal, select
        userInput = input_field.text
        if userInput == 'init':
            stopSignal = not init(debug)
        elif userInput == 'stop':
            stopSignal = stop(debug)
        elif userInput == 'exit':
            if not stopSignal:
                stop(debug)
            application.exit()
        elif 'Exploit' in select or userInput.startswith('exploit'):
            select = exploit.process(select, userInput.replace('exploit ', ''))
        elif 'Defense' in select or userInput.startswith('defense'):
            pass
        elif 'Analysis' in select or userInput.startswith('analysis'):
            select = analysis.process(select,
                                      userInput.replace('analysis ', ''))
        elif userInput.startswith('help'):
            dashboard.process(select, userInput)
        else:
            dashboard.process(select, userInput)

        input_field.text = ''

    style = Style([('output-field', 'bg:#000044 #ffffff'),
                   ('input-field', 'bg:#000000 #ffffff'), ('line', '#004400')])

    application = Application(layout=Layout(container,
                                            focused_element=input_field),
                              key_bindings=kb,
                              style=style,
                              full_screen=True)

    application.run()
Example #13
0
def pgcli_bindings(pgcli):
    """Custom key bindings for pgcli."""
    kb = KeyBindings()

    tab_insert_text = ' ' * 4

    @kb.add('f2')
    def _(event):
        """Enable/Disable SmartCompletion Mode."""
        _logger.debug('Detected F2 key.')
        pgcli.completer.smart_completion = not pgcli.completer.smart_completion

    @kb.add('f3')
    def _(event):
        """Enable/Disable Multiline Mode."""
        _logger.debug('Detected F3 key.')
        pgcli.multi_line = not pgcli.multi_line

    @kb.add('f4')
    def _(event):
        """Toggle between Vi and Emacs mode."""
        _logger.debug('Detected F4 key.')
        pgcli.vi_mode = not pgcli.vi_mode
        event.app.editing_mode = EditingMode.VI if pgcli.vi_mode else EditingMode.EMACS

    @kb.add('tab')
    def _(event):
        """Force autocompletion at cursor on non-empty lines."""

        _logger.debug('Detected <Tab> key.')

        buff = event.app.current_buffer
        doc = buff.document

        if doc.on_first_line or doc.current_line.strip():
            if buff.complete_state:
                buff.complete_next()
            else:
                buff.start_completion(select_first=True)
        else:
            buff.insert_text(tab_insert_text, fire_event=False)

    @kb.add('escape')
    def _(event):
        """Force closing of autocompletion."""
        _logger.debug('Detected <Esc> key.')

        event.current_buffer.complete_state = None
        event.app.current_buffer.complete_state = None

    @kb.add('c-space')
    def _(event):
        """
        Initialize autocompletion at cursor.

        If the autocompletion menu is not showing, display it with the
        appropriate completions for the context.

        If the menu is showing, select the next completion.
        """
        _logger.debug('Detected <C-Space> key.')

        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=False)

    @kb.add('enter', filter=completion_is_selected)
    def _(event):
        """Makes the enter key work as the tab key only when showing the menu.

        In other words, don't execute query when enter is pressed in
        the completion dropdown menu, instead close the dropdown menu
        (accept current selection).

        """
        _logger.debug('Detected enter key.')

        event.current_buffer.complete_state = None
        event.app.current_buffer.complete_state = None

    return kb
Example #14
0
def key_press_menu(menu_items, loop_display=""):
    bindings = KeyBindings()
    message = get_menu(menu_items)
    global key_pressed
    key_pressed = ""

    @bindings.add('c-m')
    @bindings.add('up')
    @bindings.add('left')
    @bindings.add('right')
    @bindings.add('escape', eager=True)
    @bindings.add('down')
    @bindings.add('<any>')
    def _(event):
        event.app.exit()
        global key_pressed
        key_pressed = str(event.key_sequence[0].key)

    session = PromptSession()
    loop = True
    current_key = 0
    key_positions = []
    for i, m in enumerate(message):
        if m[0] == "class:key":
            key_positions.append(i)

    while loop:
        if len(loop_display) > 0:
            print_formatted_text(FormattedText(loop_display), style=style)

        for k in key_positions:
            if not message[
                    k]:  # ignore menu items that don't have a message binding
                continue
            message[k] = ('class:key', message[k][1])
            message[k + 1] = ('class:menu_item', message[k + 1][1])
        message[key_positions[current_key]] = (
            'class:current_key', message[key_positions[current_key]][1])
        message[key_positions[current_key] +
                1] = ('class:current_key',
                      message[key_positions[current_key] + 1][1])

        session.prompt(message, style=style, key_bindings=bindings)
        if str(key_pressed) == "Keys.Up":
            if current_key > 0:
                current_key = current_key - 1
            clear()
            continue

        if str(key_pressed) == "Keys.Down":
            if current_key < len(key_positions) - 1:
                current_key = current_key + 1
            clear()
            continue

        if str(key_pressed) == "Keys.ControlM":  # enter has been pressed
            key_pressed = message[key_positions[current_key]][1].split(
                ")")[0][1:]

        if str(key_pressed) == "Keys.Escape":  # enter has been pressed
            key_pressed = "escape"
            loop = False
            return key_pressed

        if not (str(key_pressed) in list(menu_items.keys())):
            clear()
            continue
        else:
            loop = False
            break

    return key_pressed
Example #15
0
def question(message, **kwargs):
    # TODO add bottom-bar (Move up and down to reveal more choices)
    # TODO extract common parts for list, checkbox, rawlist, expand
    # TODO validate
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')
    # this does not implement default, use checked...
    if 'default' in kwargs:
        raise ValueError('Checkbox does not implement \'default\' '
                         'use \'checked\':True\' in choice!')

    choices = kwargs.pop('choices', None)
    validator = setup_simple_validator(kwargs)

    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    pointer_index = kwargs.pop('pointer_index', 0)
    additional_parameters = dict()

    # windows pointer fix
    if get_platform() == 'Windows':
        additional_parameters.update(
            {"pointer_sign": kwargs.pop('pointer_sign', '>')})
    else:
        additional_parameters.update(
            {"pointer_sign": kwargs.pop('pointer_sign', '\u276F')})
    #additional_parameters.update({"selected_sign": kwargs.pop('selected_sign', '\u25C9')})
    additional_parameters.update(
        {"unselected_sign": kwargs.pop('selected_sign', '\u25EF')})
    additional_parameters.update(
        {"unselected_sign": kwargs.pop('unselected_sign', '\u25EF')})

    ic = InquirerControl(choices, pointer_index, **additional_parameters)
    qmark = kwargs.pop('qmark', '[?]')

    def get_prompt_tokens():
        tokens = []

        tokens.append(('class:questionmark', qmark))
        tokens.append(('class:question', ' %s ' % message))
        if ic.answered:
            nbr_selected = len(ic.selected_options)
            if nbr_selected == 0:
                tokens.append(('class:answer', ' done'))
            elif nbr_selected == 1:
                tokens.append(
                    ('class:answer', ' [%s]' % ic.selected_options[0]))
            else:
                tokens.append(
                    ('class:answer', ' done (%d selections)' % nbr_selected))
        else:
            tokens.append(('class:instruction',
                           ' (<up>, <down> to move, <space> to select, <a> '
                           'to toggle, <i> to invert)'))
            if not ic.answered_correctly:
                tokens.append(('class:error', ' Error: %s' % ic.error_message))
        return tokens

    # assemble layout
    layout = HSplit([
        Window(
            height=D.exact(1),
            content=FormattedTextControl(get_prompt_tokens),
            always_hide_cursor=True,
        ),
        ConditionalContainer(Window(ic,
                                    width=D.exact(43),
                                    height=D(min=3),
                                    scroll_offsets=ScrollOffsets(top=1,
                                                                 bottom=1)),
                             filter=~IsDone())
    ])

    # key bindings
    kb = KeyBindings()

    @kb.add('c-q', eager=True)
    @kb.add('c-c', eager=True)
    def _(event):
        event.app.exit(result=None)

    @kb.add(' ', eager=True)
    def toggle(event):
        pointed_choice = ic.choices[ic.pointer_index][1]  # value
        if pointed_choice in ic.selected_options:
            ic.selected_options.remove(pointed_choice)
        else:
            ic.selected_options.append(pointed_choice)

    @kb.add('i', eager=True)
    def invert(event):
        inverted_selection = [
            c[1] for c in ic.choices if not isinstance(c, Separator)
            and c[1] not in ic.selected_options and not c[2]
        ]
        ic.selected_options = inverted_selection

    @kb.add('a', eager=True)
    def all(event):
        all_selected = True  # all choices have been selected
        for c in ic.choices:
            if not isinstance(c, Separator) and c[
                    1] not in ic.selected_options and not c[2]:
                # add missing ones
                ic.selected_options.append(c[1])
                all_selected = False
        if all_selected:
            ic.selected_options = []

    @kb.add('down', eager=True)
    @kb.add('j', eager=True)
    def move_cursor_down(event):
        def _next():
            ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count)

        _next()
        while isinstance(ic.choices[ic.pointer_index], Separator) or \
                ic.choices[ic.pointer_index][2]:
            _next()

    @kb.add('up', eager=True)
    @kb.add('k', eager=True)
    def move_cursor_up(event):
        def _prev():
            ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count)

        _prev()
        while isinstance(ic.choices[ic.pointer_index], Separator) or \
                ic.choices[ic.pointer_index][2]:
            _prev()

    @kb.add('enter', eager=True)
    def set_answer(event):
        ic.answered = True
        # TODO use validator
        event.app.exit(result=ic.get_selected_values())

    return Application(layout=Layout(layout),
                       key_bindings=kb,
                       mouse_support=True,
                       style=style)
Example #16
0
from slick.bencode import File

potential_commands = [
    "/send ",
    "/get ",
    "/end ",
    "/ls ",
    "/list ",
    "/talk ",
    "/add ",
    "/remove ",
    "/help ",
    "/info ",
]

bindings = KeyBindings()


@bindings.add("c-w")
def back_a_word(event):
    buff = event.app.current_buffer
    matches = list(re.finditer(r"([ /])", buff.text))
    if matches:
        match = matches[-1]
        new_text = buff.text[:match.end() - 1]
        buff.text = new_text
        buff._set_cursor_position(match.end() - 1)


class CommandValidator(Validator):
    def validate(self, document):
Example #17
0
def browse():
    """
    A browser for the bibmanager database.
    """
    # Content of the text buffer:
    bibs = bm.load()
    keys = [bib.key for bib in bibs]
    all_compact_text = "\n".join(keys)
    all_expanded_text = "\n\n".join(bib.meta() + bib.content for bib in bibs)
    # A list object, since I want this to be a global variable
    selected_content = [None]

    lex_style = style_from_pygments_cls(
        pygments.styles.get_style_by_name(cm.get('style')))
    custom_style = Style.from_dict({
        "status": "reverse",
        "status.position": "#aaaa00",
        "status.key": "#ffaa00",
        "shadow": "bg:#440044",
        "not-searching": "#888888",
    })
    style = merge_styles([lex_style, custom_style])

    def get_menubar_text():
        return [
            ("class:status", " ("),
            ("class:status.key", "enter"),
            ("class:status", ")select entry  ("),
            ("class:status.key", "e"),
            ("class:status", ")xpand entry  ("),
            ("class:status.key", "f"),
            ("class:status", ")ind  ("),
            ("class:status.key", "s"),
            ("class:status", ")ave  ("),
            ("class:status.key", "h"),
            ("class:status", ")elp  ("),
            ("class:status.key", "q"),
            ("class:status", ")uit"),
        ]

    def get_menubar_right_text():
        """Get index of entry under cursor."""
        key = get_current_key(text_field.buffer.document, keys)
        return f" {keys.index(key) + 1} "

    def get_infobar_text():
        """Get author-year-title of entry under cursor."""
        key = get_current_key(text_field.buffer.document, keys)
        bib = bibs[keys.index(key)]
        year = '' if bib.year is None else bib.year
        title = 'NO_TITLE' if bib.title is None else bib.title
        return f"{bib.get_authors('ushort')}{year}: {title}"

    search_buffer = Buffer(completer=WordCompleter(keys),
                           complete_while_typing=False,
                           multiline=False)
    literal_search_field = SearchToolbar(
        search_buffer=search_buffer,
        forward_search_prompt="Text search: ",
        backward_search_prompt="Text search backward: ",
        ignore_case=False)

    # Entry search bar:
    authors_list = [bib.authors for bib in bibs]
    firsts = sorted(
        set([
            u.get_authors([authors[0]], format='ushort')
            for authors in authors_list if authors is not None
        ]))
    firsts = [
        '^{' + first + '}' if ' ' in first else '^' + first for first in firsts
    ]

    lasts = sorted(
        set([
            u.get_authors([author], format='ushort')
            for authors in authors_list if authors is not None
            for author in authors
        ]))
    lasts = ['{' + last + '}' if ' ' in last else last for last in lasts]

    bibkeys = [bib.key for bib in bibs]
    bibcodes = [bib.bibcode for bib in bibs if bib.bibcode is not None]
    bibyears = sorted(
        set([str(bib.year) for bib in bibs if bib.year is not None]))
    titles = [bib.title for bib in bibs]
    tags = sorted(
        set(
            itertools.chain(
                *[bib.tags for bib in bibs if bib.tags is not None])))

    key_words = {
        'author:"^"': firsts,
        'author:""': lasts,
        'year:': bibyears,
        'title:""': titles,
        'key:': bibkeys,
        'bibcode:': bibcodes,
        'tags:': tags,
    }
    completer = u.DynamicKeywordCompleter(key_words)
    suggester = u.DynamicKeywordSuggester()
    auto_suggest_bindings = load_auto_suggest_bindings()

    # Searcher:
    entry_search_buffer = Buffer(
        completer=completer,
        complete_while_typing=False,
        auto_suggest=suggester,
    )

    def get_line_prefix(lineno, wrap_count):
        return FormattedText([
            ('bold', 'Entry search: '),
        ])

    entry_search_field = Window(BufferControl(
        buffer=entry_search_buffer,
        input_processors=[AppendAutoSuggestion()],
    ),
                                get_line_prefix=get_line_prefix,
                                height=1)
    # Wrap in conditional container to display it only when focused:
    entry_search_focus = Condition(
        lambda: get_app().layout.current_window == entry_search_field)
    entry_search_container = ConditionalContainer(
        content=entry_search_field,
        filter=entry_search_focus,
    )

    text_field = TextArea(
        text=all_compact_text,
        lexer=PygmentsLexer(BibTeXLexer),
        scrollbar=True,
        line_numbers=False,
        read_only=True,
        search_field=literal_search_field,
        input_processors=[HighlightEntryProcessor()],
    )
    text_field.buffer.name = 'text_area_buffer'
    text_field.is_expanded = False
    text_field.compact_text = all_compact_text
    text_field.expanded_text = all_expanded_text
    # Shortcut to HighlightEntryProcessor:
    for processor in text_field.control.input_processors:
        if processor.__class__.__name__ == 'HighlightEntryProcessor':
            text_field.bm_processor = processor
    # Do not highlight searched text:
    sp = text_field.control.default_input_processors[0]
    sp._classname = ' '
    sp._classname_current = ' '

    menu_bar = VSplit(
        [
            Window(FormattedTextControl(get_menubar_text),
                   style="class:status"),
            Window(FormattedTextControl(get_menubar_right_text),
                   style="class:status.right",
                   width=9,
                   align=WindowAlign.RIGHT),
        ],
        height=1,
    )

    info_bar = ConditionalContainer(
        content=Window(
            content=FormattedTextControl(get_infobar_text),
            height=D.exact(1),
            style="class:status",
        ),
        filter=~entry_search_focus,
    )

    body = HSplit([
        menu_bar,
        text_field,
        literal_search_field,
        entry_search_container,
        info_bar,
    ])

    root_container = FloatContainer(
        content=body,
        floats=[
            Float(
                xcursor=True,
                ycursor=True,
                content=CompletionsMenu(max_height=16, scroll_offset=1),
            ),
        ],
    )

    # Key bindings:
    bindings = KeyBindings()

    text_focus = Condition(
        lambda: get_app().layout.current_window == text_field.window)
    dialog_focus = Condition(
        lambda: hasattr(get_app().layout.current_window, 'dialog'))

    @bindings.add("q", filter=text_focus)
    def _quit(event):
        event.app.exit()

    # Navigation:
    @bindings.add("g", filter=text_focus)
    def _go_to_first_line(event):
        event.current_buffer.cursor_position = 0

    @bindings.add("G", filter=text_focus)
    def _go_to_last_line(event) -> None:
        event.current_buffer.cursor_position = len(event.current_buffer.text)

    @bindings.add("d", filter=text_focus)
    def _scroll_down(event):
        scroll_half_page_down(event)

    @bindings.add("u", filter=text_focus)
    def _scroll_up(event):
        scroll_half_page_up(event)

    @bindings.add("n", filter=text_focus)
    def _find_next(event):
        search_state = event.app.current_search_state
        event.current_buffer.apply_search(search_state,
                                          include_current_position=False,
                                          count=event.arg)

    @bindings.add("N", filter=text_focus)
    def _find_previous(event):
        search_state = event.app.current_search_state
        event.current_buffer.apply_search(~search_state,
                                          include_current_position=False,
                                          count=event.arg)

    @bindings.add("h", filter=text_focus)
    def _show_help(event):
        show_message("Shortcuts", help_message)

    @bindings.add("f", filter=text_focus)
    def _start_literal_search(event):
        search.start_search(direction=search.SearchDirection.FORWARD)

    # TBD: Remove 't' binding no before 17/12/2022
    @bindings.add("t", filter=text_focus)
    @bindings.add("k", filter=text_focus)
    def _start_entry_search(event):
        text_field.current_key = get_current_key(event.current_buffer.document,
                                                 keys)
        event.app.layout.focus(entry_search_field)

    @bindings.add("b", filter=text_focus)
    def _open_in_browser(event):
        key = get_current_key(event.current_buffer.document, keys)
        bib = bm.find(key=key, bibs=bibs)
        if bib.adsurl is not None:
            webbrowser.open(bib.adsurl, new=2)
        else:
            show_message("Message", f"Entry '{key}' does not have an ADS url.")

    @bindings.add("c-c", filter=dialog_focus)
    def _close_dialog(event):
        get_app().layout.current_window.dialog.future.set_result(None)

    @bindings.add("s", filter=text_focus)
    def _save_selected_to_file(event):
        selected = text_field.bm_processor.selected_entries
        if len(selected) == 0:
            show_message("Message", "Nothing to save.")
            return

        async def coroutine():
            dialog = TextInputDialog(
                title="Save to File",
                label_text="\nEnter a file path or leave blank to quit "
                "and print to screen:\n(press Control-c to cancel)\n",
                completer=PathCompleter(),
            )
            path = await show_dialog_as_float(dialog)
            content = '\n\n'.join(bibs[keys.index(key)].content
                                  for key in selected)
            if path == "":
                selected_content[0] = content
                # The program termination is in TextInputDialog() since I
                # need to close this coroutine first.
                return
            if path is not None:
                try:
                    with open(path, "w") as f:
                        f.write(content)
                except IOError as e:
                    show_message("Error", str(e))

        ensure_future(coroutine())

    @bindings.add("enter", filter=text_focus)
    def _toggle_selected_entry(event):
        "Select/deselect entry pointed by the cursor."
        key = get_current_key(event.current_buffer.document, keys)
        text_field.bm_processor.toggle_selected_entry(key)

    @bindings.add("enter", filter=entry_search_focus)
    def _select_entries(event):
        "Parse the input tag text and send focus back to main text."
        # Reset tag text to '':
        doc = event.current_buffer.document
        start_pos = doc.cursor_position + doc.get_start_of_line_position()
        event.current_buffer.cursor_position = start_pos
        event.current_buffer.delete(doc.get_end_of_line_position() -
                                    doc.get_start_of_line_position())

        # Catch text and parse search text:
        matches = u.parse_search(doc.current_line)
        if len(matches) == 0:
            text_field.compact_text = all_compact_text[:]
            text_field.expanded_text = all_expanded_text[:]
            search_buffer.completer.words = keys
        else:
            text_field.compact_text = "\n".join([bib.key for bib in matches])
            text_field.expanded_text = "\n\n".join(bib.meta() + bib.content
                                                   for bib in matches)
            search_buffer.completer.words = [bib.key for bib in matches]

        # Return focus to main text:
        event.app.layout.focus(text_field.window)

        # Update main text with selected tag:
        buffer = event.current_buffer
        text_field.text = text_field.compact_text
        if text_field.current_key in search_buffer.completer.words:
            buffer_position = text_field.text.index(text_field.current_key)
        else:
            buffer_position = 0
        buffer.cursor_position = buffer_position
        text_field.is_expanded = False

    # TBD: Remove 'T' binding no before 17/12/2022
    @bindings.add("T", filter=text_focus)
    @bindings.add("K", filter=text_focus)
    def _deselect_tags(event):
        buffer = event.current_buffer
        key = get_current_key(buffer.document, keys)
        text_field.compact_text = all_compact_text[:]
        text_field.expanded_text = all_expanded_text[:]
        search_buffer.completer.words = keys
        # Update main text:
        text_field.text = text_field.compact_text
        buffer.cursor_position = buffer.text.index(key)
        text_field.is_expanded = False

    @bindings.add("e", filter=text_focus)
    def _expand_collapse_entry(event):
        "Expand/collapse current entry."
        doc = event.current_buffer.document
        key, start_end, is_expanded = get_current_key(doc,
                                                      keys,
                                                      get_start_end=True,
                                                      get_expanded=True)
        bib = bm.find(key=key, bibs=bibs)
        if is_expanded:
            # Remove blank lines around if surrounded by keys:
            start_row, _ = doc._find_line_start_index(start_end[0])
            if start_row > 0 and doc.lines[start_row - 2] in keys:
                start_end[0] -= 1
            end_row, _ = doc._find_line_start_index(start_end[1])
            if end_row < doc.line_count - 1 and doc.lines[end_row + 2] in keys:
                start_end[1] += 1
            event.app.clipboard.set_text(bib.key)
        else:
            expanded_content = bib.meta() + bib.content
            row = doc.cursor_position_row
            # Add blank lines around if surrounded by keys:
            if row > 0 and doc.lines[row - 1] != '':
                expanded_content = '\n' + expanded_content
            if row < doc.line_count - 1 and doc.lines[row + 1] != '':
                expanded_content = expanded_content + '\n'
            event.app.clipboard.set_text(expanded_content)

        text_field.read_only = False
        event.current_buffer.cursor_position = start_end[0]
        event.current_buffer.delete(count=start_end[1] - start_end[0])
        event.current_buffer.paste_clipboard_data(
            event.app.clipboard.get_data(),
            count=event.arg,
            paste_mode=PasteMode.VI_BEFORE)
        text_field.read_only = True
        if is_expanded:
            event.current_buffer.cursor_position = start_end[0]

    @bindings.add("E", filter=text_focus)
    def _expand_collapse_all(event):
        "Expand/collapse all entries."
        buffer = event.current_buffer
        key = get_current_key(buffer.document, keys)
        if text_field.is_expanded:
            text_field.text = text_field.compact_text
        else:
            text_field.text = text_field.expanded_text

        buffer.cursor_position = buffer.text.index(key)
        text_field.is_expanded = not text_field.is_expanded

    @bindings.add("o", filter=text_focus)
    def _open_pdf(event):
        buffer = event.current_buffer
        key = get_current_key(buffer.document, keys)
        bib = bm.find(key=key, bibs=bibs)

        has_pdf = bib.pdf is not None
        has_bibcode = bib.bibcode is not None
        is_missing = has_pdf and not os.path.exists(f'{u.BM_PDF()}{bib.pdf}')

        if not has_pdf and not has_bibcode:
            show_message("Message",
                         f"BibTeX entry '{key}' does not have a PDF.")
            return

        if has_pdf and not is_missing:
            pm.open(key=key)
            return

        if has_pdf and is_missing and not has_bibcode:
            show_message(
                "Message",
                f"BibTeX entry has a PDF file: {bib.pdf}, but the file "
                "could not be found.")
            return

        # Need to fetch before opening:
        async def coroutine():
            dialog = MessageDialog(
                "PDF file not found",
                "Fetch from ADS?\n(might take a few seconds ...)",
                asking=True)
            fetch = await show_dialog_as_float(dialog)
            if fetch:
                with io.StringIO() as buf, redirect_stdout(buf):
                    fetched = pm.fetch(bib.bibcode, replace=True)
                    fetch_output = buf.getvalue()

                if fetched is None:
                    show_message("PDF fetch failed", fetch_output)
                else:
                    show_message("PDF fetch succeeded.", fetch_output)
                    pm.open(key=key)

        ensure_future(coroutine())

    key_bindings = merge_key_bindings([
        auto_suggest_bindings,
        bindings,
    ])
    application = Application(
        layout=Layout(root_container, focused_element=text_field),
        key_bindings=key_bindings,
        enable_page_navigation_bindings=True,
        style=style,
        full_screen=True,
    )

    application.run()
    if selected_content[0] is not None:
        tokens = list(pygments.lex(selected_content[0], lexer=BibTeXLexer()))

        print_formatted_text(
            PygmentsTokens(tokens),
            end="",
            style=lex_style,
            #output=create_output(sys.stdout),
        )
    MenuItem('View', children=[
        MenuItem('Status Bar'),
    ]),
    MenuItem('Info', children=[
        MenuItem('About'),
    ]),
], floats=[
    Float(xcursor=True,
          ycursor=True,
          content=CompletionsMenu(
              max_height=16,
              scroll_offset=1)),
])

# Global key bindings.
bindings = KeyBindings()
bindings.add('tab')(focus_next)
bindings.add('s-tab')(focus_previous)


style = Style.from_dict({
    'window.border': '#888888',
    'shadow': 'bg:#222222',

    'menu-bar': 'bg:#aaaaaa #888888',
    'menu-bar.selected-item': 'bg:#ffffff #000000',
    'menu': 'bg:#888888 #ffffff',
    'menu.border': '#aaaaaa',
    'window.border shadow': '#444444',

    'focused  button': 'bg:#880000 #ffffff noinherit',
    def init_prompt_toolkit_cli(self):
        if self.simple_prompt or ('JUPYTER_CONSOLE_TEST' in os.environ):
            # Simple restricted interface for tests so we can find prompts with
            # pexpect. Multi-line input not supported.
            @asyncio.coroutine
            def prompt():
                prompt = 'In [%d]: ' % self.execution_count
                raw = yield from async_input(prompt)
                return raw

            self.prompt_for_code = prompt
            self.print_out_prompt = \
                lambda: print('Out[%d]: ' % self.execution_count, end='')
            return

        kb = KeyBindings()
        insert_mode = vi_insert_mode | emacs_insert_mode

        @kb.add("enter",
                filter=(has_focus(DEFAULT_BUFFER)
                        & ~has_selection
                        & insert_mode))
        def _(event):
            b = event.current_buffer
            d = b.document
            if not (d.on_last_line or d.cursor_position_row >=
                    d.line_count - d.empty_line_count_at_the_end()):
                b.newline()
                return

            # Pressing enter flushes any pending display. This also ensures
            # the displayed execution_count is correct.
            self.handle_iopub()

            more, indent = self.check_complete(d.text)

            if (not more) and b.accept_handler:
                b.validate_and_handle()
            else:
                b.insert_text('\n' + indent)

        @kb.add("c-c", filter=has_focus(DEFAULT_BUFFER))
        def _(event):
            event.current_buffer.reset()

        @kb.add("c-\\", filter=has_focus(DEFAULT_BUFFER))
        def _(event):
            raise EOFError

        @kb.add("c-z",
                filter=Condition(lambda: suspend_to_background_supported()))
        def _(event):
            event.cli.suspend_to_background()

        # Pre-populate history from IPython's history database
        history = InMemoryHistory()
        last_cell = u""
        for _, _, cell in self.history_manager.get_tail(
                self.history_load_length, include_latest=True):
            # Ignore blank lines and consecutive duplicates
            cell = cell.rstrip()
            if cell and (cell != last_cell):
                history.append_string(cell)

        style_overrides = {
            Token.Prompt: '#009900',
            Token.PromptNum: '#00ff00 bold',
            Token.OutPrompt: '#ff2200',
            Token.OutPromptNum: '#ff0000 bold',
            Token.RemotePrompt: '#999900',
        }
        if self.highlighting_style:
            style_cls = get_style_by_name(self.highlighting_style)
        else:
            style_cls = get_style_by_name('default')
            # The default theme needs to be visible on both a dark background
            # and a light background, because we can't tell what the terminal
            # looks like. These tweaks to the default theme help with that.
            style_overrides.update({
                Token.Number: '#007700',
                Token.Operator: 'noinherit',
                Token.String: '#BB6622',
                Token.Name.Function: '#2080D0',
                Token.Name.Class: 'bold #2080D0',
                Token.Name.Namespace: 'bold #2080D0',
            })
        style_overrides.update(self.highlighting_style_overrides)
        style = merge_styles([
            style_from_pygments_cls(style_cls),
            style_from_pygments_dict(style_overrides),
        ])

        editing_mode = getattr(EditingMode, self.editing_mode.upper())
        langinfo = self.kernel_info.get('language_info', {})
        lexer = langinfo.get('pygments_lexer', langinfo.get('name', 'text'))

        # If enabled in the settings, highlight matching brackets
        # when the DEFAULT_BUFFER has the focus
        input_processors = [
            ConditionalProcessor(
                processor=HighlightMatchingBracketProcessor(chars='[](){}'),
                filter=has_focus(DEFAULT_BUFFER) & ~is_done
                & Condition(lambda: self.highlight_matching_brackets))
        ]

        # Tell prompt_toolkit to use the asyncio event loop.
        # Obsolete in prompt_toolkit.v3
        if not PTK3:
            use_asyncio_event_loop()

        self.pt_cli = PromptSession(
            message=(lambda: PygmentsTokens(self.get_prompt_tokens())),
            multiline=True,
            editing_mode=editing_mode,
            lexer=PygmentsLexer(get_pygments_lexer(lexer)),
            prompt_continuation=(
                lambda width, lineno, is_soft_wrap: PygmentsTokens(
                    self.get_continuation_tokens(width))),
            key_bindings=kb,
            history=history,
            completer=JupyterPTCompleter(self.Completer),
            enable_history_search=True,
            style=style,
            input_processors=input_processors,
            color_depth=(ColorDepth.TRUE_COLOR if self.true_color else None),
        )
Example #20
0
def create_ipython_shortcuts(shell):
    """Set up the prompt_toolkit keyboard shortcuts for IPython"""

    kb = KeyBindings()
    insert_mode = vi_insert_mode | emacs_insert_mode

    if getattr(shell, 'handle_return', None):
        return_handler = shell.handle_return(shell)
    else:
        return_handler = newline_or_execute_outer(shell)

    kb.add('enter', filter=(has_focus(DEFAULT_BUFFER)
                            & ~has_selection
                            & insert_mode
                        ))(return_handler)

    kb.add('c-\\')(force_exit)

    kb.add('c-p', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
                )(previous_history_or_previous_completion)

    kb.add('c-n', filter=(vi_insert_mode & has_focus(DEFAULT_BUFFER))
                )(next_history_or_next_completion)

    kb.add('c-g', filter=(has_focus(DEFAULT_BUFFER) & has_completions)
                )(dismiss_completion)

    kb.add('c-c', filter=has_focus(DEFAULT_BUFFER))(reset_buffer)

    kb.add('c-c', filter=has_focus(SEARCH_BUFFER))(reset_search_buffer)

    supports_suspend = Condition(lambda: hasattr(signal, 'SIGTSTP'))
    kb.add('c-z', filter=supports_suspend)(suspend_to_bg)

    # Ctrl+I == Tab
    kb.add('tab', filter=(has_focus(DEFAULT_BUFFER)
                          & ~has_selection
                          & insert_mode
                          & cursor_in_leading_ws
                        ))(indent_buffer)

    kb.add('c-o', filter=(has_focus(DEFAULT_BUFFER)
                  & emacs_insert_mode))(newline_autoindent_outer(shell.input_splitter))

    kb.add('f2', filter=has_focus(DEFAULT_BUFFER))(open_input_in_editor)

    if shell.display_completions == 'readlinelike':
        kb.add('c-i', filter=(has_focus(DEFAULT_BUFFER)
                              & ~has_selection
                              & insert_mode
                              & ~cursor_in_leading_ws
                        ))(display_completions_like_readline)

    if sys.platform == 'win32':
        kb.add('c-v', filter=(has_focus(DEFAULT_BUFFER) & ~vi_mode))(win_paste)

    return kb
Example #21
0
# styl rámce
style = "bg:#ansiblue #ansiwhite"

# správce rozvržení
vsplit = HSplit([
    VSplit([Frame(widget1, style=style),
            Frame(widget2, style=style)]),
    Frame(TextArea(), title="Editor"),
    Frame(widget3, style=style),
])

layout = Layout(vsplit)

# napojení na klávesové zkratky
key_bindings = KeyBindings()


@key_bindings.add("escape")
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()


def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
                              full_screen=True)
Example #22
0
def confirm(message: Text,
            default: bool = True,
            qmark: Text = DEFAULT_QUESTION_PREFIX,
            style: Optional[Style] = None,
            **kwargs: Any) -> Question:
    """Prompt the user to confirm or reject.

       This question type can be used to prompt the user for a confirmation
       of a yes-or-no question. If the user just hits enter, the default
       value will be returned.

       Args:
           message: Question text

           default: Default value will be returned if the user just hits
                    enter.

           qmark: Question prefix displayed in front of the question.
                  By default this is a `?`

           style: A custom color and style for the question parts. You can
                  configure colors as well as font types for different elements.

       Returns:
           Question: Question instance, ready to be prompted (using `.ask()`).
       """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    status = {'answer': None}

    def get_prompt_tokens():
        tokens = []

        tokens.append(("class:qmark", qmark))
        tokens.append(("class:question", ' {} '.format(message)))

        if status['answer'] is not None:
            answer = ' {}'.format(YES if status['answer'] else NO)
            tokens.append(("class:answer", answer))
        else:
            instruction = ' {}'.format(YES_OR_NO if default else NO_OR_YES)
            tokens.append(("class:instruction", instruction))

        return to_formatted_text(tokens)

    bindings = KeyBindings()

    @bindings.add(Keys.ControlQ, eager=True)
    @bindings.add(Keys.ControlC, eager=True)
    def _(event):
        event.app.exit(exception=KeyboardInterrupt, style='class:aborting')

    @bindings.add('n')
    @bindings.add('N')
    def key_n(event):
        status['answer'] = False
        event.app.exit(result=False)

    @bindings.add('y')
    @bindings.add('Y')
    def key_y(event):
        status['answer'] = True
        event.app.exit(result=True)

    @bindings.add(Keys.ControlM, eager=True)
    def set_answer(event):
        status['answer'] = default
        event.app.exit(result=default)

    @bindings.add(Keys.Any)
    def other(event):
        """Disallow inserting other text."""
        pass

    return Question(
        PromptSession(get_prompt_tokens,
                      key_bindings=bindings,
                      style=merged_style,
                      **kwargs).app)
Example #23
0
def checkbox(
    message: str,
    choices: Sequence[Union[str, Choice, Dict[str, Any]]],
    default: Optional[str] = None,
    validate: Callable[[List[str]], bool] = lambda a: True,
    qmark: str = DEFAULT_QUESTION_PREFIX,
    style: Optional[Style] = None,
    use_pointer: bool = True,
    initial_choice: Optional[Union[str, Choice, Dict[str, Any]]] = None,
    **kwargs: Any,
) -> Question:
    """Ask the user to select from a list of items.

    This is a multiselect, the user can choose one, none or many of the
    items.

    Args:
        message: Question text

        choices: Items shown in the selection, this can contain `Choice` or
                 or `Separator` objects or simple items as strings. Passing
                 `Choice` objects, allows you to configure the item more
                 (e.g. preselecting it or disabling it).

        default: Default return value (single value). If you want to preselect
                 multiple items, use `Choice("foo", checked=True)` instead.

        validate: Require the entered value to pass a validation. The
                  value can not be submitted until the validator accepts
                  it (e.g. to check minimum password length).

                  This should be a function accepting the input and
                  returning a boolean. An optional second return value
                  is the error message to display.

        qmark: Question prefix displayed in front of the question.
               By default this is a `?`

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

        use_pointer: Flag to enable the pointer in front of the currently
                     highlighted element.

        initial_choice: A value corresponding to a selectable item in the choices,
                        to initially set the pointer position to.

    Returns:
        Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([
        DEFAULT_STYLE,
        # Disable the default inverted colours bottom-toolbar behaviour (for
        # the error message). However it can be re-enabled with a custom
        # style.
        Style([("bottom-toolbar", "noreverse")]),
        style,
    ])

    if not callable(validate):
        raise ValueError("validate must be callable")

    ic = InquirerControl(choices,
                         default,
                         use_pointer=use_pointer,
                         initial_choice=initial_choice)

    def get_prompt_tokens() -> List[Tuple[str, str]]:
        tokens = []

        tokens.append(("class:qmark", qmark))
        tokens.append(("class:question", " {} ".format(message)))

        if ic.is_answered:
            nbr_selected = len(ic.selected_options)
            if nbr_selected == 0:
                tokens.append(("class:answer", " done"))
            elif nbr_selected == 1:
                if isinstance(ic.get_selected_values()[0].title, list):
                    ts = ic.get_selected_values()[0].title
                    tokens.append((
                        "class:answer",
                        "".join([token[1] for token in ts]),  # type:ignore
                    ))
                else:
                    tokens.append((
                        "class:answer",
                        " [{}]".format(ic.get_selected_values()[0].title),
                    ))
            else:
                tokens.append(("class:answer",
                               " done ({} selections)".format(nbr_selected)))
        else:
            tokens.append((
                "class:instruction",
                " (Use arrow keys to move, "
                "<space> to select, "
                "<a> to toggle, "
                "<i> to invert)",
            ))
        return tokens

    def get_selected_values() -> List[Any]:
        return [c.value for c in ic.get_selected_values()]

    def perform_validation(selected_values: List[str]) -> bool:

        verdict = validate(selected_values)

        if isinstance(verdict, bool):
            valid = verdict
            error_message = FormattedText([("class:validation-toolbar",
                                            "Invalid selection")])
        else:
            valid, error_message = verdict

            if isinstance(error_message, str):
                error_message = FormattedText([("class:validation-toolbar",
                                                error_message)])

        ic.error_message = (error_message
                            if not valid and ic.submission_attempted else None)

        return valid

    layout = common.create_inquirer_layout(ic, get_prompt_tokens, **kwargs)

    bindings = KeyBindings()

    @bindings.add(Keys.ControlQ, eager=True)
    @bindings.add(Keys.ControlC, eager=True)
    def _(event):
        event.app.exit(exception=KeyboardInterrupt, style="class:aborting")

    @bindings.add(" ", eager=True)
    def toggle(_event):
        pointed_choice = ic.get_pointed_at().value
        if pointed_choice in ic.selected_options:
            ic.selected_options.remove(pointed_choice)
        else:
            ic.selected_options.append(pointed_choice)

        perform_validation(get_selected_values())

    @bindings.add("i", eager=True)
    def invert(_event):
        inverted_selection = [
            c.value for c in ic.choices if not isinstance(c, Separator)
            and c.value not in ic.selected_options and not c.disabled
        ]
        ic.selected_options = inverted_selection

        perform_validation(get_selected_values())

    @bindings.add("a", eager=True)
    def all(_event):
        all_selected = True  # all choices have been selected
        for c in ic.choices:
            if (not isinstance(c, Separator)
                    and c.value not in ic.selected_options and not c.disabled):
                # add missing ones
                ic.selected_options.append(c.value)
                all_selected = False
        if all_selected:
            ic.selected_options = []

        perform_validation(get_selected_values())

    @bindings.add(Keys.Down, eager=True)
    @bindings.add("j", eager=True)
    def move_cursor_down(_event):
        ic.select_next()
        while not ic.is_selection_valid():
            ic.select_next()

    @bindings.add(Keys.Up, eager=True)
    @bindings.add("k", eager=True)
    def move_cursor_up(_event):
        ic.select_previous()
        while not ic.is_selection_valid():
            ic.select_previous()

    @bindings.add(Keys.ControlM, eager=True)
    def set_answer(event):

        selected_values = get_selected_values()
        ic.submission_attempted = True

        if perform_validation(selected_values):
            ic.is_answered = True
            event.app.exit(result=selected_values)

    @bindings.add(Keys.Any)
    def other(_event):
        """Disallow inserting other text. """
        pass

    return Question(
        Application(
            layout=layout,
            key_bindings=bindings,
            style=merged_style,
            **utils.used_kwargs(kwargs, Application.__init__),
        ))
Example #24
0
def question(message, **kwargs):
    # TODO extract common parts for list, checkbox, rawlist, expand
    # TODO up, down navigation
    if not 'choices' in kwargs:
        raise PromptParameterException('choices')

    choices = kwargs.pop('choices', None)
    default = kwargs.pop('default', None)
    qmark = kwargs.pop('qmark', '?')
    # TODO style defaults on detail level
    style = kwargs.pop('style', default_style)

    ic = InquirerControl(choices, default)

    def get_prompt_tokens():
        tokens = []

        tokens.append(('class:questionmark', qmark))
        tokens.append(('class:question', ' %s ' % message))
        if not ic.answered:
            tokens.append(('class:instruction', ' (%s)' % ''.join(
                [k[0] for k in ic.choices if not isinstance(k, Separator)])))
        else:
            tokens.append(('class:answer', ' %s' % ic.get_selected_value()))
        return tokens

    #@Condition
    #def is_help_active():
    #    return ic._help_active

    # assemble layout
    layout = HSplit([
        Window(
            height=D.exact(1),
            content=FormattedTextControl(get_prompt_tokens),
            always_hide_cursor=True,
        ),
        ConditionalContainer(
            Window(ic, always_hide_cursor=True),
            #filter=is_help_active & ~IsDone()  # ~ bitwise inverse
            filter=~IsDone()  # ~ bitwise inverse
        )
    ])

    # key bindings
    kb = KeyBindings()

    @kb.add('c-q', eager=True)
    @kb.add('c-c', eager=True)
    def _(event):
        event.app.exit(result=None)
        #raise KeyboardInterrupt()

    # add key bindings for choices
    for i, c in enumerate(ic.choices):
        if not isinstance(c, Separator):

            def _reg_binding(i, keys):
                # trick out late evaluation with a "function factory":
                # http://stackoverflow.com/questions/3431676/creating-functions-in-a-loop
                @kb.add(keys, eager=True)
                def select_choice(event):
                    ic.pointer_index = i

            if c[0] not in ['h', 'H']:
                _reg_binding(i, c[0])
                if c[0].isupper():
                    _reg_binding(i, c[0].lower())

    @kb.add('H', eager=True)
    @kb.add('h', eager=True)
    def help_choice(event):
        ic._help_active = not ic._help_active

    @kb.add('enter', eager=True)
    def set_answer(event):
        selected_value = ic.get_selected_value()
        if selected_value == '__HELP__':
            ic._help_active = True
        else:
            ic.answered = True
            event.app.exit(result=selected_value)

    return Application(layout=Layout(layout),
                       key_bindings=kb,
                       mouse_support=True,
                       style=style)
Example #25
0
class PymuxKeyBindings(object):
    """
    Pymux key binding manager.
    """
    def __init__(self, pymux):
        self.pymux = pymux

        def get_search_state():
            " Return the currently active SearchState. (The one for the focused pane.) "
            return pymux.arrangement.get_active_pane().search_state

        self.custom_key_bindings = KeyBindings()

        self.key_bindings = merge_key_bindings([
            self._load_builtins(),
            self.custom_key_bindings,
        ])

        self._prefix = ('c-b', )
        self._prefix_binding = None

        # Load initial bindings.
        self._load_prefix_binding()

        # Custom user configured key bindings.
        # { (needs_prefix, key) -> (command, handler) }
        self.custom_bindings = {}

    def _load_prefix_binding(self):
        """
        Load the prefix key binding.
        """
        pymux = self.pymux

        # Remove previous binding.
        if self._prefix_binding:
            self.custom_key_bindings.remove_binding(self._prefix_binding)

        # Create new Python binding.
        @self.custom_key_bindings.add(*self._prefix, filter=
            ~(HasPrefix(pymux) | has_focus(COMMAND) | has_focus(PROMPT) |
              WaitsForConfirmation(pymux)))
        def enter_prefix_handler(event):
            " Enter prefix mode. "
            pymux.get_client_state().has_prefix = True

        self._prefix_binding = enter_prefix_handler

    @property
    def prefix(self):
        " Get the prefix key. "
        return self._prefix

    @prefix.setter
    def prefix(self, keys):
        """
        Set a new prefix key.
        """
        assert isinstance(keys, tuple)

        self._prefix = keys
        self._load_prefix_binding()

    def _load_builtins(self):
        """
        Fill the Registry with the hard coded key bindings.
        """
        pymux = self.pymux
        kb = KeyBindings()

        # Create filters.
        has_prefix = HasPrefix(pymux)
        waits_for_confirmation = WaitsForConfirmation(pymux)
        prompt_or_command_focus = has_focus(COMMAND) | has_focus(PROMPT)
        display_pane_numbers = Condition(lambda: pymux.display_pane_numbers)
        in_scroll_buffer_not_searching = InScrollBufferNotSearching(pymux)

        @kb.add(Keys.Any, filter=has_prefix)
        def _(event):
            " Ignore unknown Ctrl-B prefixed key sequences. "
            pymux.get_client_state().has_prefix = False

        @kb.add('c-c', filter=prompt_or_command_focus & ~has_prefix)
        @kb.add('c-g', filter=prompt_or_command_focus & ~has_prefix)
#        @kb.add('backspace', filter=has_focus(COMMAND) & ~has_prefix &
#                              Condition(lambda: cli.buffers[COMMAND].text == ''))
        def _(event):
            " Leave command mode. "
            pymux.leave_command_mode(append_to_history=False)

        @kb.add('y', filter=waits_for_confirmation)
        @kb.add('Y', filter=waits_for_confirmation)
        def _(event):
            """
            Confirm command.
            """
            client_state = pymux.get_client_state()

            command = client_state.confirm_command
            client_state.confirm_command = None
            client_state.confirm_text = None

            pymux.handle_command(command)

        @kb.add('n', filter=waits_for_confirmation)
        @kb.add('N', filter=waits_for_confirmation)
        @kb.add('c-c' , filter=waits_for_confirmation)
        def _(event):
            """
            Cancel command.
            """
            client_state = pymux.get_client_state()
            client_state.confirm_command = None
            client_state.confirm_text = None

        @kb.add('c-c', filter=in_scroll_buffer_not_searching)
        @kb.add('enter', filter=in_scroll_buffer_not_searching)
        @kb.add('q', filter=in_scroll_buffer_not_searching)
        def _(event):
            " Exit scroll buffer. "
            pane = pymux.arrangement.get_active_pane()
            pane.exit_scroll_buffer()

        @kb.add(' ', filter=in_scroll_buffer_not_searching)
        def _(event):
            " Enter selection mode when pressing space in copy mode. "
            event.current_buffer.start_selection(selection_type=SelectionType.CHARACTERS)

        @kb.add('enter', filter=in_scroll_buffer_not_searching & has_selection)
        def _(event):
            " Copy selection when pressing Enter. "
            clipboard_data = event.current_buffer.copy_selection()
            event.app.clipboard.set_data(clipboard_data)

        @kb.add('v', filter=in_scroll_buffer_not_searching & has_selection)
        def _(event):
            " Toggle between selection types. "
            types = [SelectionType.LINES, SelectionType.BLOCK, SelectionType.CHARACTERS]
            selection_state = event.current_buffer.selection_state

            try:
                index = types.index(selection_state.type)
            except ValueError:  # Not in list.
                index = 0

            selection_state.type = types[(index + 1) % len(types)]

        @Condition
        def popup_displayed():
            return self.pymux.get_client_state().display_popup

        @kb.add('q', filter=popup_displayed, eager=True)
        def _(event):
            " Quit pop-up dialog. "
            self.pymux.get_client_state().display_popup = False

        @kb.add(Keys.Any, eager=True, filter=display_pane_numbers)
        def _(event):
            " When the pane numbers are shown. Any key press should hide them. "
            pymux.display_pane_numbers = False

        @Condition
        def clock_displayed():
            " "
            pane = pymux.arrangement.get_active_pane()
            return pane.clock_mode

        @kb.add(Keys.Any, eager=True, filter=clock_displayed)
        def _(event):
            " When the clock is displayed. Any key press should hide it. "
            pane = pymux.arrangement.get_active_pane()
            pane.clock_mode = False

        return kb

    def add_custom_binding(self, key_name, command, arguments, needs_prefix=False):
        """
        Add custom binding (for the "bind-key" command.)
        Raises ValueError if the give `key_name` is an invalid name.

        :param key_name: Pymux key name, for instance "C-a" or "M-x".
        """
        assert isinstance(key_name, six.text_type)
        assert isinstance(command, six.text_type)
        assert isinstance(arguments, list)

        # Unbind previous key.
        self.remove_custom_binding(key_name, needs_prefix=needs_prefix)

        # Translate the pymux key name into a prompt_toolkit key sequence.
        # (Can raise ValueError.)
        keys_sequence = pymux_key_to_prompt_toolkit_key_sequence(key_name)

        # Create handler and add to Registry.
        if needs_prefix:
            filter = HasPrefix(self.pymux)
        else:
            filter = ~HasPrefix(self.pymux)

        filter = filter & ~(WaitsForConfirmation(self.pymux) |
                            has_focus(COMMAND) | has_focus(PROMPT))

        def key_handler(event):
            " The actual key handler. "
            call_command_handler(command, self.pymux, arguments)
            self.pymux.get_client_state().has_prefix = False

        self.custom_key_bindings.add(*keys_sequence, filter=filter)(key_handler)

        # Store key in `custom_bindings` in order to be able to call
        # "unbind-key" later on.
        k = (needs_prefix, key_name)
        self.custom_bindings[k] = CustomBinding(key_handler, command, arguments)

    def remove_custom_binding(self, key_name, needs_prefix=False):
        """
        Remove custom key binding for a key.

        :param key_name: Pymux key name, for instance "C-A".
        """
        k = (needs_prefix, key_name)

        if k in self.custom_bindings:
            self.custom_key_bindings.remove(self.custom_bindings[k].handler)
            del self.custom_bindings[k]
Example #26
0
            HSplit(
                [
                    VSplit(
                        [btn_start, btn_pause, btn_reset, btn_reset_all, btn_exit],
                        padding=1,
                        style="bg:#cccccc",
                    ),
                    text_window,
                ]
            ),
)

layout = Layout(container=root_container, focused_element=btn_start)

# Key bindings. These values are set in pydoro_core/config.py.
kb = KeyBindings()

# WHY: string to action map to allow for easy configuration
actions = {
    "focus_next": focus_next,
    "focus_previous": focus_previous,
    "exit_clicked": exit_clicked,
}

for action, keys in DEFAULT_KEY_BINDINGS.items():
    for key in keys:
        kb.add(key)(actions[action])

# Styling.
style = Style(
    [
Example #27
0
    def __init__(self, player, nameOfShop, shopInventory, shopKeeperAsciiArt=None, customCurrency=None):
        '''shopInventory is a list of items'''
        self.player = player
        self.name = nameOfShop
        self.shopInventory = shopInventory
        self.shopKeeperAsciiArt = shopKeeperAsciiArt
        if self.shopKeeperAsciiArt == None:
            self.shopKeeperAsciiArt ='''
     _\|/^
      (_oo     what can i get for ya
       |     
      /|\\
       |
       LL
            '''
          
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
                ('', ' '),
                ('#cc00cc', self.playerClans, "utf-8"),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
            ]) 
        if customCurrency == None: self.currency = "dollars"
        else: self.currency = customCurrency
        self.result = None

        self.buySellRadiosRows = []
        self.listOfItems = []
        self.populateBuySellRadios() # declares self.buySellRadios
        self.currentRadios = self.buySellRadios
        self.rightWindowDescription = self.buySellRadios.description # description is whataver is in the description box on the right
        self.requestingConfirmation = False
        self.playerIs = "at buy/sell menu"
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.handleEscape)

        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getShopContainer(),
                focused_element=self.buySellRadios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )
Example #28
0
def list_choice_menu(
    choices: List[Choice[T]],
    message: str,
    default: Optional[Choice[T]] = None,
    back: Optional[Callable] = None,
    quit_option_text: Optional[str] = QUIT,
    use_ctrl_c_to_quit: bool = True,
) -> Optional[T]:
    """
    Displays a list menu

    Parameters
    ----------
    choices: List[ChoiceT]
        A list of `ChoiceT` that the user can chose from in the menu
    message: str
        The question to be displayed at the top of the choice menu
    default: Optional[Choice[T]]
        The default answer
    back: Optional[Callable[]]
        The function to call if the user choses to go back
        Leave blank if you don't want a "BACK" option
    quit_option_text: Optional[str]
        The text to display for the bottom "QUIT" option
        If you don't want a "QUIT" option, set this parameter to None
    use_ctrl_c_to_quit: bool
        Whether or not Ctrl C is intercepted to quit the menu
        When it is, the information is appended to the `quit_option_text`
        Defaults to True

    Returns
    -------
    Optional[T]
        - The choice that the user made
        - None if he chose to go back

    Raises
    ------
    UserExit
        When the user chose the "Quit" alternative
    """
    if use_ctrl_c_to_quit:
        kb = KeyBindings()

        def quit_menu(event):
            event.app.exit(exception=UserExit())

        kb.add(Keys.ControlC, eager=True)(quit_menu)

        if quit_option_text:
            quit_option_text += ' (Ctrl+c)'

    menu_choices = deepcopy(choices)
    if back:
        menu_choices.extend([Choice.separator(), Choice.from_string(BACK)])
    if quit_option_text:
        menu_choices.extend(
            [Choice.separator(),
             Choice.from_string(quit_option_text)])

    question_args = {
        'type': 'listmenu',
        'name': 'action',
        'message': message,
        'choices': menu_choices,
        'default': default,
    }
    if use_ctrl_c_to_quit:
        question_args['key_bindings'] = kb

    questions = [question_args]
    answers = prompt(questions)
    action = answers['action']
    if action == quit_option_text:
        raise UserExit()
    if action == BACK:
        back(
        )  # type:ignore  # mypy can't see that action can't be BACK if back is NONE
        return None
    else:
        return action
Example #29
0
        self.dialog = Dialog(
            title=title,
            body=HSplit([Label(text=text),]),
            buttons=[ok_button],
            width=D(preferred=80),
            modal=True,
        )

    def __pt_container__(self):
        return self.dialog



# Global key bindings
# -------------------
BINDINGS = KeyBindings()

# New file
@BINDINGS.add('c-n')
def _(event):
    'New File'

# Open file
@BINDINGS.add('c-o')
def _(event):
    'Open'
    do_open_file(None)

# Save
@BINDINGS.add('c-s')
def _(event):
Example #30
0
def get_commands(app: Application) -> Tuple[List[Command], KeyBindings]:

    kb = KeyBindings()
    keys_info = get_keys_info()

    @kb.add('c-q')  # type: ignore
    @kb.add('c-c')  # type: ignore
    def exit(event: Event) -> None:
        event.app.deselect()
        event.app.exit()

    @kb.add(
        'enter',  # type: ignore
        filter=has_focus(app.options_list.search_buffer))
    def select(event: Event) -> None:
        event.app.exit()

    @kb.add(
        keys_info["open_document_key"]["key"],  # type: ignore
        filter=has_focus(app.options_list.search_buffer))
    def open(cmd: Command) -> None:
        from papis.commands.open import run
        docs = cmd.app.get_selection()
        for doc in docs:
            run(doc)

    @kb.add(
        keys_info["edit_document_key"]["key"],  # type: ignore
        filter=has_focus(app.options_list.search_buffer))
    def edit(cmd: Command) -> None:
        from papis.commands.edit import run
        docs = cmd.app.get_selection()
        for doc in docs:
            run(doc)
        cmd.app.renderer.clear()

    @kb.add(
        keys_info["edit_notes_key"]["key"],  # type: ignore
        filter=has_focus(app.options_list.search_buffer))
    def edit_notes(cmd: Command) -> None:
        from papis.commands.edit import edit_notes
        docs = cmd.app.get_selection()
        for doc in docs:
            edit_notes(doc)
        cmd.app.renderer.clear()

    @kb.add(
        keys_info["show_help_key"]["key"],  # type: ignore
        filter=~has_focus(app.help_window))
    def help(event: Event) -> None:
        event.app.layout.focus(app.help_window.window)
        event.app.message_toolbar.text = 'Press q to quit'

    # def _echo(cmd, *args) -> None:
    # cmd.app.message_toolbar.text = ' '.join(args)

    @kb.add(
        keys_info["show_info_key"]["key"],  # type: ignore
        filter=~has_focus(app.info_window))
    def info(cmd: Command) -> None:
        cmd.app.update_info_window()
        cmd.app.layout.focus(cmd.app.info_window.window)

    @kb.add('c-g', 'g')  # type: ignore
    @kb.add(keys_info["go_top_key"]["key"])  # type: ignore
    def go_top(event: Event) -> None:
        event.app.options_list.go_top()
        event.app.refresh()

    @kb.add('c-g', 'G')  # type: ignore
    @kb.add(keys_info["go_bottom_key"]["key"])  # type: ignore
    def go_end(event: Event) -> None:
        event.app.options_list.go_bottom()
        event.app.refresh()

    return (
        [
            Command("open", run=open, aliases=["op"]),
            Command("edit", run=edit, aliases=["e"]),
            Command("select", run=select, aliases=["e"]),
            Command("exit", run=exit, aliases=["quit", "q"]),
            Command("info", run=info, aliases=["i"]),
            Command("go_top", run=go_top),
            Command("go_bottom", run=go_end),
            Command("move_down", run=lambda c: c.app.options_list.move_down()),
            Command("move_up", run=lambda c: c.app.options_list.move_up()),
            # Command("echo", run=_echo),
            Command("help", run=help),
        ],
        kb)
Example #31
0
class CombatUI():

    def __init__(self, player, enemy, song='worry 2.wav'):
        self.song = Sound( player,fileName = song, loop=-1)
        self.player = player
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', str(player.aspect['name'])),
                ('', ' '),
                ('#cc00cc', str(self.playerClans)),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', str(player.aspect['name'])),
            ]) 
        self.enemy = enemy

        self.playerGoesNext = True # by default, enemy always gets first strike
        self.playerJustDodged = False
        self.escapeTries = 0
        self.escapeChance = .3

        self.battleLog = '\n\n\n\n\n\n'
        self.maxHeightOfBattleLogWindow = 7
        self.totalWidth = 90
        self.actionsWidth = 30
        self.statsWidth = 20 

        self.selectedIndexText = ''
        self.result = None

        self.playerHPBar = ProgressBar()
        self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp)) 
        self.enemyHPBar = ProgressBar()
        self.setHealthProgressBar(self.enemyHPBar, 100) 

        self.radios = RadioList(
            values=[ #value, lable
                ('Attack', 'Attack'), # use eqipped weapon
                ('Dodge', 'Dodge'), # icrease miss chance for enemy
                ('Item', 'Item'),
                ('Run', 'Run') # try to escape
                # more options could be:
                # check - returns text about enemy potentially indicating weaknessess
            ],
            player = self.player,
            width = self.actionsWidth)
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.tryToEscape)
        # self.bindings.add('up')(self.setSelectedIndexTextUp)
        # TODO: make secret easter egg key bindings # self.bindings.add('a', 'a')(self.test)  
        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getRootContainer(),
                focused_element=self.radios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )

    

    # call this function to change the value a progress bar (prog) to a percent
    def setHealthProgressBar(self,progbar, percent):
        if percent < 0: # should never happen but for safety
            percent = 0
        progbar.container = FloatContainer(
            content=Window(height=1),
            floats=[
                Float(left=0, top=0, right=0, bottom=0, content=VSplit([
                    Window(style='bg:#00cc00', # health, green
                            width=lambda: D(weight=int(percent))),
                    Window(style='bg:#ff0000', # damage, red
                            width=lambda: D(weight=int(100 - percent))),
                ])),
            ])

    def toPercent(self, value, max):
        return int(100*(float(value)/float(max)))

    def handleEnter(self, event):
        if not self.playerGoesNext: # check if it's actually your turn
            return
        self.playerGoesNext = False

        choice = self.radios.values[self.radios._selected_index][0] 
        s = ''
        if choice == "Attack":
            self.attackEnemy()
            return # return early so attackEnemy can go to enemy turn so damaging consunmables work
        elif choice == "Dodge": # dodging increases chance for enemy to miss by 30% SCALING
            s += "You tried to dodge... "
            self.playerJustDodged = True 
        elif choice == "Item": # doesnt take your turn
            self.playerGoesNext = True
            self.done(result='inventory')
            return
        elif choice == "Run":
            s += self.tryToEscape()
        else:
            s += "How did you do that!?"
        
        self.enemyTurn(s)

    def attackEnemy(self, alwaysHit=True, consumableDamage=None, consumableName=None ):
        s = ''
        if not consumableDamage == None: # if has consumable damage
            damage = consumableDamage # better also have a name
            s += "You threw the " + str(consumableName) + "... "
        else:
            s +=  "You tried to attack... "
            damage = self.player.getTotalAttackPower()
        s += " and did " 
        s += str(damage)
        s += " damage!" # TODO color
        self.enemy.hp = self.enemy.hp - int(damage)
        if self.enemy.hp < 0:
            self.enemy.hp = 0
        self.setHealthProgressBar(self.enemyHPBar, self.toPercent(self.enemy.hp, self.enemy.maxhp))
        self.enemyTurn(s)
    
    def tryToEscape(self, event=None):
        s = ''
        s += "You tried to run..." 
        randomChance = random.uniform(0,1) - (self.escapeTries-1) *.1 # each try makes it 10 percent easier to escape after first try
        if self.escapeChance > randomChance and self.escapeTries>0: #has to have already tried to escape once
            s += " and escaped the combat!" # TODO advanced combat: isnt ever visible
            self.done("escaped")
        else:
            s += " but failed to escape!"
        self.escapeTries += 1
        return s

    def enemyTurn(self, textOfPlayerTurn=False):
        if self.enemy.hp == 0: # check if he dead
            self.done("win")
            return
        # for now, always try to attack TODO advanced combat
        self.playerGoesNext = True
        s=''
        s += self.enemy.name + " tried to " 
        attack = self.enemy.getRandomAttack() 
        if attack[-1] == "*": # if attack finishes the sentence
            s += attack[:-1] # remove *
        else :
            s += str(attack)
            s += " you... "
            
        # calculate hit chance and handle
        dodgeModifier = 0 # TODO advanced combat dodge modifier
        if self.playerJustDodged == True:
            dodgeModifier = 30
            self.playerJustDodged = False
        if self.enemy.missChancePercent + dodgeModifier > random.randint(0,100):
            # missed
            if not attack[-1] == "*": s += " but missed!"
            else: s += " But missed!"
        else:
            # hit
            damage = self.enemy.attack
            if not attack[-1] == "*": s += " and dealt " + str(damage) + " damage!"
            else: 
                s += " It dealt " + str(damage) + " damage!"
            self.player.hp = self.player.hp - damage # lose health
            #t1 = threading.Thread(target=self.rollNumbers(self.player.hp, self.player.hp - damage), args=())
            #t1.start()
            # self.rollNumbers(self.player.hp, self.player.hp - damage)

            if self.player.hp < 0:
                self.player.hp = 0
            self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp))
            if self.player.hp == 0: #dead
                # TODO make death less awkwawrd
                self.done("lose")
                return
        if textOfPlayerTurn: 
            self.battleLog = textOfPlayerTurn + '\n\n' + s 
        else:
            self.battleLog = s 
        self.refresh()

    def rollNumbers(self, start, end, speed=1.5):
        r = start-end # range
        maxSpeed = .01
        if r < 0: r *= -1
        startTime = .5
        for t in range(r):
            startTime /= speed
        time = startTime
        for c in range(r+1):
            s = int(start - c )
            self.player.hp = s
            self.refresh()
            if time < maxSpeed:
                wait(maxSpeed)
            else:
                wait(time)
            time *= speed 

    def refresh(self):
        self.fillBattleLogWithNewlines()
        self.application.layout=Layout(
            self.getRootContainer(),
            focused_element=self.radios)

    def fillBattleLogWithNewlines(self):
        self.battleLog = wrap(self.battleLog, limit=self.totalWidth-self.actionsWidth-self.statsWidth)
        slicedBattleLog = self.battleLog.split('\n') # list of rows of the battlelog
        while True:
            if len(slicedBattleLog) < self.maxHeightOfBattleLogWindow: 
                slicedBattleLog.append('\n') 
            else:
                break
        self.battleLog = '\n'.join(slicedBattleLog)

    # def suspense(self): # doesnt work because ui updates on run method, not during other methods
    #     for i in range(3):
    #         wait(.5)
    #         self.battleLog += '.'
    #         self.refresh()

    def makeFormattedText(self, text, color='#ffffff'):
        return FormattedText([
            (color, str(text)) 
        ])

    # returns new root container (updates text and stuff)
    def getRootContainer(self):
        height = self.maxHeightOfBattleLogWindow
        enemyName = self.makeFormattedText(self.enemy.name) 
        battleLogTitle = FormattedText([
            ('#ffffff', "Battle Log") 
        ])
        actionsTitle = FormattedText([
            ('#ffffff', "Actions") 
        ])
        statsTitle = FormattedText([
            ('#ffffff', "Stats") 
        ])
        root_container = HSplit([
            VSplit([
                Dialog( # actions
                    title=actionsTitle,
                    body=HSplit([
                        self.radios,
                    ], height= height),
                    width=self.actionsWidth
                ), # battlelog 
                Dialog(
                    title = battleLogTitle,
                    body=Label(self.battleLog),
                    width=self.totalWidth-self.actionsWidth - self.statsWidth
                ),
                Dialog( # stats
                    title = statsTitle,
                    body=Label(getStats(self.player)),
                    width=self.statsWidth ,
                ),
            ], padding=0, width = self.actionsWidth, height=height+2 ),
            # health bars #
            VSplit([ 
                Frame(
                    body=self.playerHPBar,
                    title=self.playerName,
                    width=int(self.totalWidth/2)
                ),
                Frame(
                    body=self.enemyHPBar,
                    title=enemyName,
                    width=int(self.totalWidth/2)
                ), 
            ], padding=0, width = self.totalWidth)
        ])
        return root_container

    def run(self):
        self.application.run()

    def done(self, result='?'):
        self.result = result
        if self.result != 'inventory':
            self.song.stopSound()
        get_app().exit(result=self.result)
Example #32
0
class ShopUI():

    def __init__(self, player, nameOfShop, shopInventory, shopKeeperAsciiArt=None, customCurrency=None):
        '''shopInventory is a list of items'''
        self.player = player
        self.name = nameOfShop
        self.shopInventory = shopInventory
        self.shopKeeperAsciiArt = shopKeeperAsciiArt
        if self.shopKeeperAsciiArt == None:
            self.shopKeeperAsciiArt ='''
     _\|/^
      (_oo     what can i get for ya
       |     
      /|\\
       |
       LL
            '''
          
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
                ('', ' '),
                ('#cc00cc', self.playerClans, "utf-8"),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
            ]) 
        if customCurrency == None: self.currency = "dollars"
        else: self.currency = customCurrency
        self.result = None

        self.buySellRadiosRows = []
        self.listOfItems = []
        self.populateBuySellRadios() # declares self.buySellRadios
        self.currentRadios = self.buySellRadios
        self.rightWindowDescription = self.buySellRadios.description # description is whataver is in the description box on the right
        self.requestingConfirmation = False
        self.playerIs = "at buy/sell menu"
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.handleEscape)

        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getShopContainer(),
                focused_element=self.buySellRadios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )

    def handleEscape(self, event):
        self.requestingConfirmation = False
        if self.currentRadios == self.buySellRadios:
            self.done()
        else: # return to main page
            self.playerIs = "at buy/sell menu"
            self.populateBuySellRadios()
            self.currentRadios = self.buySellRadios
            # self.description = self.buySellRadios.description
            self.refresh()

    def handleEnter(self, event):
        if self.requestingConfirmation:
            self.requestingConfirmation = False
            if self.playerIs == "buying":
                self.buy()
                self.listOfItems = self.shopInventory
            elif self.playerIs == "selling":
                self.sell()
                self.listOfItems = self.player.getAllInventoryItemsAsObjectList()
            if self.handleEmptiness(self.listOfItems): return
            self.makeListCurrentRadios(self.listOfItems) 
            # TODO sound music, sound effect of eating a consumable
            return

        elif self.currentRadios == self.buySellRadios: # if on main page
            if self.currentRadios._selected_index == 0: # BUY, show shops inventory
                self.playerIs = "buying"
                self.listOfItems = self.shopInventory
            elif self.currentRadios._selected_index == 1: # SELL, show player inventory
                self.playerIs = "selling"
                self.listOfItems = self.player.getAllInventoryItemsAsObjectList()
            else:log("what the f**k")
            if self.handleEmptiness(self.listOfItems): return
            self.makeListCurrentRadios(self.listOfItems) 
        elif self.currentRadios == self.selectedRadios: # if not on main page
            self.requestingConfirmation = True
            price = self.getCurrentlySelectedItem().sellValue
            if price == 1 and self.currency.endswith('s'): currency = 'dollar'
            else: currency = self.currency
            nameOfItem = self.getCurrentlySelectedItem().name
            if self.playerIs == "buying":
                self.refresh(setDescription="Purchase " + str(nameOfItem) +" for " + str(price) + " " + currency + "?")
            elif self.playerIs == "selling":
                self.refresh(setDescription="Sell " + str(nameOfItem) +" for " + str(price) + " " + currency + "?")

    def buy(self):
        item = self.getCurrentlySelectedItem()
        if item.sellValue > self.player.money:
            self.refresh(setDescription="You can't afford that.")
        else:
            self.player.money = self.player.money - item.sellValue # subtract funds
            self.player.money = round(self.player.money, 2) # round to cents
            item.sellValue = item.sellValue /2 # half the worth of the item after buying
            self.shopInventory.remove(item)
            self.player.addToInventory(item, printAboutIt=False)

    def sell(self):
        item = self.getCurrentlySelectedItem()
        if item.equipped == True: self.player.unequip(item=item)
        self.player.inventory.remove(item) # remove item from player inventory
        self.player.money = self.player.money + item.sellValue # get paid
        self.player.money = round(self.player.money, 2) # round just in case
        self.shopInventory.append(item) # give item to shop owner

    def getCurrentlySelectedItem(self):
        return self.listOfItems[self.currentRadios._selected_index]

    def handleEmptiness(self, lis):
        if len(self.listOfItems) == 0:
            self.currentRadios = self.buySellRadios
            if self.playerIs == "buying":
                self.playerIs = "at buy/sell menu"
                self.refresh(setDescription="Sold out!")
            elif self.playerIs == "selling":
                self.playerIs = "at buy/sell menu"
                self.refresh(setDescription="You've got nothing left!")
            return True

    def makeListCurrentRadios(self, lisp, selectedIndex=0):
        lisp = self.refreshItemDescriptions(lisp)
        self.listOfItemsTupled = self.tuplify(lisp)
        self.selectedRadios = RadioList2(
            values=self.listOfItemsTupled,
            app = self)    
        self.selectedRadios._selected_index = selectedIndex
        self.currentRadios = self.selectedRadios 
        # self.description = self.currentRadios.values[selectedIndex]
        self.refresh()

    def refreshItemDescriptions(self, lis):
        for i in lis:
            i.description = i.buildItemDescriptionString()
        return lis

    def tuplify(self, listt):
        if len(listt) == 0:
            return [] # should never see this
        newlist=[]
        for i in range(len(listt)):
            l = []
            l.append(self.unicodify(listt[i].description))
            l.append(self.unicodify(colorItem(listt[i], useGetName=True))) # colors
            newlist.append( tuple(l) )
        return newlist

    
        
    

    def refresh(self, setDescription=False):
        index = self.currentRadios._selected_index
        if setDescription:
            self.rightWindowDescription = setDescription
        else:
            self.rightWindowDescription = self.currentRadios.values[index][0]
        
        self.application.layout=Layout(
            self.getShopContainer(),
            focused_element=self.currentRadios)
            
        
    def populateBuySellRadios(self):
        self.buySellRadiosRows = []
        self.populateBuySellRadiosHelper('Buy')
        self.populateBuySellRadiosHelper('Sell')
        self.buySellRadios = RadioList2(
            values=self.buySellRadiosRows,
            app = self)

    def populateBuySellRadiosHelper(self, category):
        desc = self.shopKeeperAsciiArt
        tup = []
        tup.append(desc)
        tup.append(category.capitalize())
        self.buySellRadiosRows.append( tuple(tup) )

    def unicodify(self, text):
        if isinstance(text, str):
            return str(text)
        else:
            return text

    def getShopContainer(self):
        width = 40
        smallerWidth = 30
        statsWidth = 20
        height = 10
        if self.playerIs == "at buy/sell menu":
            leftWindowTitle = ""
            descriptionArea =makeFormattedText(self.name)
            desc = self.rightWindowDescription
        elif self.playerIs == "buying":
            leftWindowTitle = makeFormattedText(self.name)
            descriptionArea = colorItem(self.getCurrentlySelectedItem())
            desc = wrap(self.rightWindowDescription, width-2)
        elif self.playerIs == "selling":
            leftWindowTitle = makeFormattedText(self.player.aspect["name"])
            descriptionArea = colorItem(self.getCurrentlySelectedItem())
            desc = wrap(self.rightWindowDescription, width-2)
        root_container = VSplit([
            HSplit([
                Dialog(
                    title=leftWindowTitle,
                    body=HSplit([
                        self.currentRadios,
                    ], )
                ),
            ], padding=0, width = smallerWidth, ),
            HSplit([
                Dialog(
                    title = descriptionArea,
                    body=Label(desc),
                ),
            ], padding=0, width = width,),
            HSplit([
                Dialog(
                    title =  makeFormattedText("Stats"),
                    body=Label(getStats(self.player)),
                ),
            ], padding=0, width = statsWidth, height= height,),
        ])
        return root_container 

    def run(self):
        self.application.run()

    def done(self):
        self.result = "hit escape"
        get_app().exit(result="hit escape")
 
# TODO:
# colors
button4 = Button("Exit", handler=exit_clicked)

buttons = HSplit([button1, button2, button3, button4])

text_area = TextArea(focusable=False)

# správce rozvržení
root = VSplit([
    Box(Frame(buttons, style="bg:#ansiblue #ansiwhite"), padding=2),
    Box(Frame(text_area, title="Events"), padding=2),
])

layout = Layout(root)

# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add("s-tab")(focus_previous)
key_bindings.add("tab")(focus_next)


@key_bindings.add("escape")
def on_escape_press(event):
    """Callback funkce volaná při stisku klávesy Esc."""
    print("\n\n[escape]\n\n")
    event.app.exit()


def main():
    # vytvoření aplikace s textovým uživatelským rozhraním
    application = Application(layout=layout,
                              key_bindings=key_bindings,
Example #34
0
class InventoryUI():

    def __init__(self, player):
        self.player = player
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
                ('', ' '),
                ('#cc00cc', self.playerClans, "utf-8"),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', player.aspect['name']),
            ]) 
        self.result = None

        self.mainRadiosRows = []
        self.listOfItems = []
        self.populateMainRadios() # declares self.mainRadios
        self.currentRadios = self.mainRadios
        self.description = self.mainRadios.description # description is whataver is in the description box on the right
        self.requestingConfirmation = False
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.handleEscape)

        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getRootContainer(),
                focused_element=self.mainRadios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )

    def handleEscape(self, event):
        self.requestingConfirmation = False
        if self.currentRadios == self.mainRadios:
            self.done()
        else: # return to main page
            self.populateMainRadios()
            self.currentRadios = self.mainRadios
            # self.description = self.mainRadios.description
            self.refresh()

    def handleEnter(self, event):
        if self.requestingConfirmation:
            self.requestingConfirmation = False
            result = self.player.activateItem(self.getCurrentlySelectedItem())
            if not isinstance(result, str): # if result isnt a string
                self.done(result)# this should be different
            self.updateListOfItems()
            self.makeListCurrentRadios(self.listOfItems) 
            self.refresh(setDescription=result)
            # TODO sound music, sound effect of eating a consumable
            return

        if self.currentRadios == self.mainRadios: # if on main page
            self.updateListOfItems()
            self.makeListCurrentRadios(self.listOfItems) 
        elif self.currentRadios == self.selectedRadios: # if not on main page
            currentItem = self.listOfItems[self.currentRadios._selected_index]
            if currentItem.type == "consumable":
                if currentItem.consumable.consumableType == 'xp':
                    description = 'Eat it?'
                elif currentItem.consumable.consumableType == 'damage':
                    description = 'Throw it?'
                elif currentItem.consumable.consumableType == 'heal':
                    description = 'Eat it?'
                else:
                    description = 'Crash the game?' # shouldnt ever see
                self.requestingConfirmation = True
                self.refresh(setDescription=description)
                return
            self.player.activateItem(self.listOfItems[self.currentRadios._selected_index]) # can delete items
            self.makeListCurrentRadios(self.listOfItems,self.selectedRadios._selected_index) 

    def updateListOfItems(self):
        category = self.mainRadios.values[self.mainRadios._selected_index][1]
        if category == 'Weapons':
            self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='weapon')
        elif category == 'Armour':
            self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='armour')
        elif category == 'Consumable':
            self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='consumable')
        elif category == 'Quest':
            self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='quest')
        elif category == 'Misc':
            self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='misc')
        if len(self.listOfItems) == 0:
            self.populateMainRadios()
            self.currentRadios = self.mainRadios
            self.refresh()

    def makeListCurrentRadios(self, lisp, selectedIndex=0):
        if len(lisp) == 0:
            self.populateMainRadios()
            self.currentRadios = self.mainRadios
        else: 
            lisp = self.refreshItemDescriptions(lisp)
            self.listOfItemsTupled = self.tuplify(lisp)
            self.selectedRadios = RadioList2(
                values=self.listOfItemsTupled,
                app = self)    
            self.selectedRadios._selected_index = selectedIndex
            self.currentRadios = self.selectedRadios 
            # self.description = self.currentRadios.values[selectedIndex]
        self.refresh()

    def refreshItemDescriptions(self, lis):
        for i in lis:
            i.description = i.buildItemDescriptionString()
        return lis

    def tuplify(self, listt):
        if len(listt) == 0:
            return [] # should never see this
        newlist=[]
        for i in listt:
            l = []
            l.append(self.unicodify(i.description))
            l.append(self.unicodify(colorItem(i, useGetName=True))) # colors
            newlist.append( tuple(l) )
        return newlist

    def refresh(self, setDescription=False):
        index = self.currentRadios._selected_index
        if setDescription:
            self.description = setDescription
        else:
            self.description = self.currentRadios.values[index][0]
        
        self.application.layout=Layout(
            self.getRootContainer(),
            focused_element=self.currentRadios)
            
        
    def populateMainRadios(self):
        self.mainRadiosRows = []
        self.populateMainRadiosHelper('weapon')
        self.populateMainRadiosHelper('armour')
        self.populateMainRadiosHelper('consumable')
        self.populateMainRadiosHelper('quest')
        self.populateMainRadiosHelper('misc')
        self.mainRadios = RadioList2(
            values=self.mainRadiosRows,
            app = self)

    def populateMainRadiosHelper(self, category):
        s = self.unicodify(self.player.getAllInventoryItemsAsString(_type=category, showEquipped=True))
        if not s == '': 
            tup = []
            tup.append(s)
            if category == 'weapon': tup.append('Weapons')
            else: tup.append(category.capitalize())
            self.mainRadiosRows.append( tuple(tup) )

    def unicodify(self, text):
        if isinstance(text, str):
            return str(text)
        else:
            return text

    def getCurrentlySelectedItem(self):
        return self.listOfItems[self.currentRadios._selected_index]

    # returns new root container (updates text and stuff)
    def getRootContainer(self):
        statsWidth = 20
        largerWidth = 40
        smallerWidth = 30
        if self.currentRadios != self.mainRadios: descriptionTitle = colorItem(self.getCurrentlySelectedItem())
        else: descriptionTitle = FormattedText([('#ffffff', "Description")])
        actionsTitle = FormattedText([('#ffffff', "Inventory")])
        stats = FormattedText([('#ffffff', "Stats")])
        desc = wrap(self.description, largerWidth-2)
        root_container = VSplit([
            HSplit([
                Dialog(
                    title=actionsTitle,
                    body=HSplit([
                        self.currentRadios,
                    ], )
                ),
            ], padding=0, width = smallerWidth, ),
            HSplit([
                Dialog(
                    title = descriptionTitle,
                    body=Label(desc),
                ),
            ], padding=0, width = largerWidth, ),
            HSplit([
                Dialog(
                    title = stats,
                    body=Label(getStats(self.player)),
                    
                ),
            ], padding=0, width=statsWidth ),
        ])
        return root_container 

    def run(self):
        self.application.run()

    def done(self, result="hit escape"):
        self.result = result
        get_app().exit(result=self.result)
 
# TODO:
# colors
#!/usr/bin/env python
# vim: set fileencoding=utf-8

from prompt_toolkit import Application
from prompt_toolkit.layout import Layout, HSplit, VSplit
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
from prompt_toolkit.application.current import get_app
from prompt_toolkit.widgets import *

# napojení na klávesové zkratky
key_bindings = KeyBindings()
key_bindings.add('s-tab')(focus_previous)
key_bindings.add('tab')(focus_next)


def message(msg):
    text_area.text += msg + "\n"


@key_bindings.add('c-n')
def on_new_selected(event=None):
    message("'New' menu item selected")


@key_bindings.add('c-o')
def on_open_selected(event=None):
    message("'Open' menu item selected")


@key_bindings.add('c-s')
Example #36
0
    app = get_app()

    focused_before = app.layout.current_window
    app.layout.focus(dialog)
    result = yield dialog.future
    app.layout.focus(focused_before)

    if float_ in root_container.floats:
        root_container.floats.remove(float_)

    raise Return(result)


# Key bindings.
bindings = KeyBindings()

@bindings.add('f2')
def do_about(*event):
    show_message('etm information', about(2)[0], 0)

@bindings.add('f3')
def do_check_updates(*event):
    res = check_output("pip search etm-dgraham")
    info =  "".join( chr(x) for x in res)
    show_message("version information", info, 2)

@bindings.add('f4')
def do_system(*event):
    show_message('system information', about(22)[1], 20)
Example #37
0
    def __init__(
        self,
        *,
        prompt: str = "> ",
        commands: list[Command] | None = None,
        predefined_commands: list[ShellPredefinedCommands] | None = None,
        first_command_case_sensitive: bool = False,
        allow_shorhands: bool = True,
        allow_python_exec: bool = False,
        python_exec_prefix: str = None,
        python_exec_globals: dict[str, Any] | None = None,
        python_exec_locals: dict[str, Any] | None = None,
        end_on_ctrlc: bool = True,
        raise_on_ctrlc: bool = False,
        command_exception_traceback: bool = True,
        command_exception_traceback_locals: bool = False,
        command_exception_reraise: bool = True,
        history: bool = True,
        history_suggestions: bool = True,
        autocomplete: bool = True,
        completely_disable_bell: bool = True,
        enable_copy: bool = True,  # TODO: Make this work
        enable_paste: bool = True,  # TODO: Make this work,
        # rich_prompt: bool = False,
        dummy_shell: bool = False,
    ):
        self.prompt: str = prompt
        self.commands: dict[CommandEntryPriority, dict[str, CommandEntry]] = {
            x: {}
            for x in [y for y in CommandEntryPriority]
        }
        if predefined_commands is None:
            predefined_commands = [x for x in ShellPredefinedCommands]

        self.FIRST_COMMAND_CASE_SENSITIVE: bool = first_command_case_sensitive
        self.ALLOW_SHORTHANDS: bool = allow_shorhands
        self.ALLOW_PYTHON_EXEC: bool = allow_python_exec
        self.PYTHON_EXEC_PREFIX: str | None = python_exec_prefix
        self.PYTHON_EXEC_GLOBALS: dict[str, Any] = (
            {} if python_exec_globals is None else python_exec_globals)
        self.PYTHON_EXEC_LOCALS: dict[str,
                                      Any] = ({} if python_exec_locals is None
                                              else python_exec_locals)
        self.END_ON_CTRL_C: bool = end_on_ctrlc
        self.RAISE_ON_CTRL_C: bool = raise_on_ctrlc
        self.COMMAND_EXCEPTION_TRACEBACK: bool = command_exception_traceback
        self.COMMAND_EXCEPTION_TRACEBACK_LOCALS: bool = (
            command_exception_traceback_locals)
        self.COMMAND_EXCEPTION_RERAISE: bool = command_exception_reraise
        # self.RICH_PROMPT: bool = rich_prompt

        if completely_disable_bell:
            # `prompt_toolkit` je super, ale někdo dostal skvělý nápad implementovat v základu zvuk bez možnosti vypnutí...
            # Tím pádem si ho vypneme sami :)
            setattr(Vt100_Output, "bell", lambda _: None)
            # Pozn.: Ono to jde vypnout asi i nějak "normálně" (resp. normálněji), ale to se mi nechce řešit.
            # Vt100_Output má totiž jako parametr "enable_bell", kterým se vlastně dá disablovat bell funkce,
            # ale problém je ten, že bychom museli tedy vytvořit vlastní Vt100_Output instanci - A já nevím,
            # co za parametry tam ještě musí být, aby to fungovalo tak jak má eShrug (A navíc je dost možný
            # že se tím nějak úplně zničí terminál)

        self.IS_DUMMY_SHELL = dummy_shell
        if not dummy_shell:
            bindings = KeyBindings()
            if enable_paste:

                @bindings.add("c-v")
                def _(event: KeyPressEvent):
                    # event.current_buffer.document.paste_clipboard_data()
                    ...

            self._promt_session: PromptSession = PromptSession(
                history=None if history else DummyHistory(),
                auto_suggest=AutoSuggestFromHistory()
                if history_suggestions else None,
                completer=ShellCompleter(self) if autocomplete else None,
                complete_while_typing=False,
                # reserve_space_for_menu=0
            )

        self._should_exit: bool = False
        self._running: bool = False

        if commands is not None:
            for command in commands:
                self.add_command(command)

        for predefined_command in predefined_commands:
            if predefined_command == ShellPredefinedCommands.EXIT:
                self.add_command(
                    Command("exit", self.stop_loop, short_help="Ukončí shell"))
            elif predefined_command == ShellPredefinedCommands.HELP:
                self.add_command(
                    Command(
                        "help",
                        self.print_help,
                        short_help="Zobrazí nápovědu",
                        aliases=["?", "napoveda"],
                    ))
            elif predefined_command == ShellPredefinedCommands.PROMPT:
                parser = ShellArgumentParser()
                parser.add_argument("text",
                                    help="Nový prompt",
                                    nargs="?",
                                    default=None)
                self.add_command(
                    Command(
                        "prompt",
                        self.__prompt_command_hanlder,
                        argparser=parser,
                        short_help="Změní nebo zobrazí prompt",
                        spread_arguments=True,
                    ))
            elif predefined_command == ShellPredefinedCommands.ALIAS:
                parser = ShellArgumentParser()
                subparsers = parser.add_subparsers(
                    required=True,
                    metavar="příkaz",
                    dest="cmd",
                    parser_class=ShellArgumentParser,
                )

                # add
                parser_add = subparsers.add_parser(
                    "add",
                    help="Přidá nový alias",
                )
                parser_add.add_argument(metavar="nazev",
                                        help="Název pro nový alias",
                                        dest="alias")
                parser_add.add_argument(
                    metavar="prikaz",
                    help="Příkaz, který bude zastupován novým aliasem",
                    dest="command",
                )

                # list
                parser_list = subparsers.add_parser(
                    "list",
                    help="Vypíše všechny uživatelky vytvořené aliasy",
                )

                # delete
                parser_delete = subparsers.add_parser(
                    "delete",
                    help="Odstraní uživatelsky vytvořený alias",
                )
                parser_delete.add_argument(
                    "alias", help="Název aliasu, který se má smazat")

                self.add_command(
                    Command(
                        "alias",
                        self.__alias_command_handler,
                        argparser=parser,
                        short_help="Vytvoří alias",
                        spread_arguments=False,
                    ))
            elif predefined_command == ShellPredefinedCommands.CLEAR:
                self.add_command(
                    Command(
                        "clear",
                        cls,
                        short_help="Vyčistí konzoli/terminál",
                        aliases=["cls"],
                    ))
            elif predefined_command == ShellPredefinedCommands.RESTART:
                self.add_command(
                    Command(
                        "restart",
                        restart,
                        short_help="Restartuje program",
                        argparser=ShellArgumentParser(
                            description=
                            "Restartuje program\nPozn.: Pokud je program spuštěn v systému Windows přes CMD, může se při prvním restartu stát, že program 'dropne' do CMD zatímco stále běží. V tom případě stačí vyskočit z CMD."
                        ),
                    ))
Example #38
0
    def __init__(self, player, enemy, song='worry 2.wav'):
        self.song = Sound( player,fileName = song, loop=-1)
        self.player = player
        self.playerClans = ' '.join(self.player.clantags)
        if len(self.player.clantags) > 0 : 
            self.playerName = FormattedText([
                ('#ffffff', str(player.aspect['name'])),
                ('', ' '),
                ('#cc00cc', str(self.playerClans)),
            ]) 
        else: 
            self.playerClans =  self.playerName = FormattedText([
                ('#ffffff', str(player.aspect['name'])),
            ]) 
        self.enemy = enemy

        self.playerGoesNext = True # by default, enemy always gets first strike
        self.playerJustDodged = False
        self.escapeTries = 0
        self.escapeChance = .3

        self.battleLog = '\n\n\n\n\n\n'
        self.maxHeightOfBattleLogWindow = 7
        self.totalWidth = 90
        self.actionsWidth = 30
        self.statsWidth = 20 

        self.selectedIndexText = ''
        self.result = None

        self.playerHPBar = ProgressBar()
        self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp)) 
        self.enemyHPBar = ProgressBar()
        self.setHealthProgressBar(self.enemyHPBar, 100) 

        self.radios = RadioList(
            values=[ #value, lable
                ('Attack', 'Attack'), # use eqipped weapon
                ('Dodge', 'Dodge'), # icrease miss chance for enemy
                ('Item', 'Item'),
                ('Run', 'Run') # try to escape
                # more options could be:
                # check - returns text about enemy potentially indicating weaknessess
            ],
            player = self.player,
            width = self.actionsWidth)
        
        self.bindings = KeyBindings()
        self.bindings.add('right' )(focus_next)
        self.bindings.add('tab' )(focus_next)
        self.bindings.add('s-tab')(focus_previous)
        self.bindings.add('left')(focus_previous)
        self.bindings.add('c-m')(self.handleEnter)
        self.bindings.add('escape')(self.tryToEscape)
        # self.bindings.add('up')(self.setSelectedIndexTextUp)
        # TODO: make secret easter egg key bindings # self.bindings.add('a', 'a')(self.test)  
        self.style = Style.from_dict({
            'dialog.body':        'bg:#000000 #ffcccc', #background color, text color
        })

        self.application = Application(
            layout=Layout(
                self.getRootContainer(),
                focused_element=self.radios,
            ),
            key_bindings=self.bindings,
            style=self.style,
            mouse_support=True,
            full_screen=True,
            )
Example #39
0
def pgcli_bindings(pgcli):
    """Custom key bindings for pgcli."""
    kb = KeyBindings()

    tab_insert_text = " " * 4

    @kb.add("f2")
    def _(event):
        """Enable/Disable SmartCompletion Mode."""
        _logger.debug("Detected F2 key.")
        pgcli.completer.smart_completion = not pgcli.completer.smart_completion

    @kb.add("f3")
    def _(event):
        """Enable/Disable Multiline Mode."""
        _logger.debug("Detected F3 key.")
        pgcli.multi_line = not pgcli.multi_line

    @kb.add("f4")
    def _(event):
        """Toggle between Vi and Emacs mode."""
        _logger.debug("Detected F4 key.")
        pgcli.vi_mode = not pgcli.vi_mode
        event.app.editing_mode = EditingMode.VI if pgcli.vi_mode else EditingMode.EMACS

    @kb.add("tab")
    def _(event):
        """Force autocompletion at cursor on non-empty lines."""

        _logger.debug("Detected <Tab> key.")

        buff = event.app.current_buffer
        doc = buff.document

        if doc.on_first_line or doc.current_line.strip():
            if buff.complete_state:
                buff.complete_next()
            else:
                buff.start_completion(select_first=True)
        else:
            buff.insert_text(tab_insert_text, fire_event=False)

    @kb.add("escape", filter=has_completions)
    def _(event):
        """Force closing of autocompletion."""
        _logger.debug("Detected <Esc> key.")

        event.current_buffer.complete_state = None
        event.app.current_buffer.complete_state = None

    @kb.add("c-space")
    def _(event):
        """
        Initialize autocompletion at cursor.

        If the autocompletion menu is not showing, display it with the
        appropriate completions for the context.

        If the menu is showing, select the next completion.
        """
        _logger.debug("Detected <C-Space> key.")

        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=False)

    @kb.add("enter", filter=completion_is_selected)
    def _(event):
        """Makes the enter key work as the tab key only when showing the menu.

        In other words, don't execute query when enter is pressed in
        the completion dropdown menu, instead close the dropdown menu
        (accept current selection).

        """
        _logger.debug("Detected enter key during completion selection.")

        event.current_buffer.complete_state = None
        event.app.current_buffer.complete_state = None

    # When using multi_line input mode the buffer is not handled on Enter (a new line is
    # inserted instead), so we force the handling if we're not in a completion or
    # history search, and one of several conditions are True
    @kb.add(
        "enter",
        filter=~(completion_is_selected | is_searching)
        & buffer_should_be_handled(pgcli),
    )
    def _(event):
        _logger.debug("Detected enter key.")
        event.current_buffer.validate_and_handle()

    @kb.add("escape", "enter", filter=~vi_mode)
    def _(event):
        """Introduces a line break regardless of multi-line mode or not."""
        _logger.debug("Detected alt-enter key.")
        event.app.current_buffer.insert_text("\n")

    @kb.add("c-p", filter=~has_selection)
    def _(event):
        """Move up in history."""
        event.current_buffer.history_backward(count=event.arg)

    @kb.add("c-n", filter=~has_selection)
    def _(event):
        """Move down in history."""
        event.current_buffer.history_forward(count=event.arg)

    @kb.add("k", "j", filter=ViInsertMode())
    def _(event):
        """
        Typing 'kj' in Insert mode, should go back to navigation mode.
        """
        _logger.debug('Detected kj keys.')
        event.cli.key_processor.feed(KeyPress(Keys.Escape))

    return kb
Example #40
0
                style='class:left-pane'),
            Box(
                body=Frame(text_area),
                padding=1,
                style='class:right-pane'),
        ]),
    ]),
)

layout = Layout(
    container=root_container,
    focused_element=button1)


# Key bindings.
kb = KeyBindings()
kb.add('tab')(focus_next)
kb.add('s-tab')(focus_previous)


# Styling.
style = Style([
    ('left-pane', 'bg:#888800 #000000'),
    ('right-pane',      'bg:#00aa00 #000000'),
    ('button',          '#000000'),
    ('button-arrow',    '#000000'),
    ('button focused', 'bg:#ff0000'),
    ('text-area focused', 'bg:#ff0000'),
])

Example #41
0
def checkbox(message: Text,
             choices: List[Union[Text, Choice, Dict[Text, Any]]],
             default: Optional[Text] = None,
             qmark: Text = DEFAULT_QUESTION_PREFIX,
             style: Optional[Style] = None,
             **kwargs: Any) -> Question:
    """Ask the user to select from a list of items.

    This is a multiselect, the user can choose one, none or many of the
    items.

    Args:
        message: Question text

        choices: Items shown in the selection, this can contain `Choice` or
                 or `Separator` objects or simple items as strings. Passing
                 `Choice` objects, allows you to configure the item more
                 (e.g. preselecting it or disabeling it).

        default: Default return value (single value). If you want to preselect
                 multiple items, use `Choice("foo", checked=True)` instead.

        qmark: Question prefix displayed in front of the question.
               By default this is a `?`

        style: A custom color and style for the question parts. You can
               configure colors as well as font types for different elements.

    Returns:
        Question: Question instance, ready to be prompted (using `.ask()`).
    """

    merged_style = merge_styles([DEFAULT_STYLE, style])

    ic = InquirerControl(choices, default)

    def get_prompt_tokens():
        tokens = []

        tokens.append(("class:qmark", qmark))
        tokens.append(("class:question", ' {} '.format(message)))
        if ic.is_answered:
            nbr_selected = len(ic.selected_options)
            if nbr_selected == 0:
                tokens.append(("class:answer", ' done'))
            elif nbr_selected == 1:
                tokens.append(
                    ("class:answer",
                     ' [{}]'.format(ic.get_selected_values()[0].title)))
            else:
                tokens.append(("class:answer",
                               ' done ({} selections)'.format(nbr_selected)))
        else:
            tokens.append(("class:instruction", ' (Use arrow keys to move, '
                           '<space> to select, '
                           '<a> to toggle, '
                           '<i> to invert)'))
        return tokens

    layout = common.create_inquirer_layout(ic, get_prompt_tokens, **kwargs)

    bindings = KeyBindings()

    @bindings.add(Keys.ControlQ, eager=True)
    @bindings.add(Keys.ControlC, eager=True)
    def _(event):
        event.app.exit(exception=KeyboardInterrupt, style='class:aborting')

    @bindings.add(' ', eager=True)
    def toggle(event):
        pointed_choice = ic.get_pointed_at().value
        if pointed_choice in ic.selected_options:
            ic.selected_options.remove(pointed_choice)
        else:
            ic.selected_options.append(pointed_choice)

    @bindings.add('i', eager=True)
    def invert(event):
        inverted_selection = [
            c.value for c in ic.choices if not isinstance(c, Separator)
            and c.value not in ic.selected_options and not c.disabled
        ]
        ic.selected_options = inverted_selection

    @bindings.add('a', eager=True)
    def all(event):
        all_selected = True  # all choices have been selected
        for c in ic.choices:
            if (not isinstance(c, Separator)
                    and c.value not in ic.selected_options and not c.disabled):
                # add missing ones
                ic.selected_options.append(c.value)
                all_selected = False
        if all_selected:
            ic.selected_options = []

    @bindings.add(Keys.Down, eager=True)
    @bindings.add("j", eager=True)
    def move_cursor_down(event):
        ic.select_next()
        while not ic.is_selection_valid():
            ic.select_next()

    @bindings.add(Keys.Up, eager=True)
    @bindings.add("k", eager=True)
    def move_cursor_up(event):
        ic.select_previous()
        while not ic.is_selection_valid():
            ic.select_previous()

    @bindings.add(Keys.ControlM, eager=True)
    def set_answer(event):
        ic.is_answered = True
        event.app.exit(result=[c.value for c in ic.get_selected_values()])

    @bindings.add(Keys.Any)
    def other(event):
        """Disallow inserting other text. """
        pass

    return Question(
        Application(layout=layout,
                    key_bindings=bindings,
                    style=merged_style,
                    **kwargs))
Example #42
0
    def __init__(self,
                 project=None,
                 extra_locals=None,
                 exit_on_continue=False):
        """
        Launch the Brownie console.

        Arguments
        ---------
        project : `Project`, optional
            Active Brownie project to include in the console's local namespace.
        extra_locals: dict, optional
            Additional variables to add to the console namespace.
        exit_on_continue: bool, optional
            If True, the `continue` command causes the console to
            raise a SystemExit with error message "continue".
        """
        console_settings = CONFIG.settings["console"]

        locals_dict = dict((i, getattr(brownie, i)) for i in brownie.__all__)
        locals_dict.update(_dir=dir,
                           dir=self._dir,
                           exit=_Quitter("exit"),
                           quit=_Quitter("quit"),
                           _console=self)

        self.exit_on_continue = exit_on_continue
        if exit_on_continue:
            # add continue to the locals so we can quickly reach it via completion hints
            locals_dict["continue"] = True

        if project:
            project._update_and_register(locals_dict)

        # only make GUI available if Tkinter is installed
        try:
            Gui = importlib.import_module("brownie._gui").Gui
            locals_dict["Gui"] = Gui
        except ModuleNotFoundError:
            pass

        if extra_locals:
            locals_dict.update(extra_locals)

        # create prompt session object
        history_file = str(_get_data_folder().joinpath(".history").absolute())
        kwargs = {}
        if console_settings["show_colors"]:
            kwargs.update(
                lexer=PygmentsLexer(PythonLexer),
                style=style_from_pygments_cls(
                    get_style_by_name(console_settings["color_style"])),
                include_default_pygments_style=False,
            )
        if console_settings["auto_suggest"]:
            kwargs["auto_suggest"] = ConsoleAutoSuggest(self, locals_dict)
        if console_settings["completions"]:
            kwargs["completer"] = ConsoleCompleter(self, locals_dict)
        if console_settings["editing_mode"]:
            kwargs["editing_mode"] = EditingMode(
                console_settings["editing_mode"].upper())

        self.compile_mode = "single"
        self.prompt_session = PromptSession(
            history=SanitizedFileHistory(history_file, locals_dict),
            input=self.prompt_input,
            key_bindings=KeyBindings(),
            **kwargs,
        )

        # add custom bindings
        key_bindings = self.prompt_session.key_bindings
        key_bindings.add(Keys.BracketedPaste)(self.paste_event)

        key_bindings.add("c-i")(self.tab_event)
        key_bindings.get_bindings_for_keys(
            ("c-i", ))[-1].filter = lambda: not self.tab_filter()

        # modify default bindings
        key_bindings = load_key_bindings()
        key_bindings.get_bindings_for_keys(
            ("c-i", ))[-1].filter = self.tab_filter

        if console_settings["auto_suggest"]:
            # remove the builtin binding for auto-suggest acceptance
            key_bindings = self.prompt_session.app.key_bindings
            accept_binding = key_bindings.get_bindings_for_keys(("right", ))[0]
            key_bindings._bindings2.remove(accept_binding.handler)

        # this is required because of a pytest conflict when using the debugging console
        if sys.platform == "win32":
            import colorama

            colorama.init()

        super().__init__(locals_dict)
    def __init__(self, exchange, get_paths_in_directory):
        super().__init__()
        self.use_default_bindings = False
        self._exchange = exchange

        self._input = TextArea(text="/project/", multiline=False)
        self._buffer = self._input.buffer
        self._buffer.cursor_position = len(self._buffer.text)
        self._completions_component = Completions()
        self._completer = AsyncCompleter(exchange, get_paths_in_directory)
        self._completer_status_component = AsyncCompleterStatus()
        self._bottom_toolbar = Window(
            FormattedTextControl(
                "[tab] Enter selected directory  "
                "[return] Choose selected directory  "
                "[arrows] Navigation  "
                "[C-c] Quit"
            ),
            height=1,
            style="reverse",
        )
        self._container = HSplit(
            [
                Window(height=1),
                Window(
                    FormattedTextControl(
                        "Choose directory to synchronize to on Faculty Platform: "
                    ),
                    height=1,
                ),
                self._input,
                Window(height=1),
                self._completions_component.container,
                self._completer_status_component.container,
            ]
        )
        self.main_container = HSplit(
            [VSplit([Window(width=2), self._container]), self._bottom_toolbar]
        )
        self._buffer.on_text_changed += self._handle_text_changed

        self.bindings = KeyBindings()

        @self.bindings.add("down")
        def _(event):
            self._completions_component.move_selection_down()

        @self.bindings.add("up")
        def _(event):
            self._completions_component.move_selection_up()

        @self.bindings.add("tab")
        def _(event):
            current_selection = self._completions_component.current_selection()
            if current_selection is not None:
                self._buffer.cursor_position = 0
                self._buffer.text = current_selection + "/"
                self._buffer.cursor_position = len(self._buffer.text)

        @self.bindings.add("enter")
        def _(event):
            current_selection = self._completions_component.current_selection()
            self._exchange.publish(
                Messages.VERIFY_REMOTE_DIRECTORY, current_selection
            )

        @self.bindings.add("c-c")
        def _(event):
            self._exchange.publish(Messages.STOP_CALLED)

        self._exchange.subscribe(
            RemoteDirMessages.NEW_SUBDIRECTORIES_WALKED,
            lambda _: self._handle_text_changed(),
        )
        self._exchange.subscribe(
            RemoteDirMessages.SUBDIRECTORY_WALKER_STATUS_CHANGE,
            lambda path: self._handle_walker_status_change(path),
        )