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, )
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 __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 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
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
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): '''
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"),
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
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
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__), ))
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. """
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()
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
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
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)
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):
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), )
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
# 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)
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)
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__), ))
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)
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]
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( [
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 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
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):
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)
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)
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,
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')
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)
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." ), ))
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, )
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
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'), ])
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))
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), )