def load_key_bindings(): """ Create a KeyBindings object that contains the default key bindings. """ all_bindings = merge_key_bindings([ # Load basic bindings. load_basic_bindings(), # Load emacs bindings. load_emacs_bindings(), load_emacs_search_bindings(), # Load Vi bindings. load_vi_bindings(), load_vi_search_bindings(), ]) return merge_key_bindings([ # Make sure that the above key bindings are only active if the # currently focussed control is a `BufferControl`. For other controls, we # don't want these key bindings to intervene. (This would break "ptterm" # for instance, which handles 'Keys.Any' in the user control itself.) ConditionalKeyBindings(all_bindings, buffer_has_focus), # Active, even when no buffer has been focussed. load_mouse_bindings(), load_cpr_bindings(), ])
def load_key_bindings(): """ Create a KeyBindings object that contains the default key bindings. """ all_bindings = merge_key_bindings([ # Load basic bindings. load_basic_bindings(), # Load emacs bindings. load_emacs_bindings(), load_emacs_search_bindings(), # Load Vi bindings. load_vi_bindings(), load_vi_search_bindings(), ]) return merge_key_bindings([ # Make sure that the above key bindings are only active if the # currently focused control is a `BufferControl`. For other controls, we # don't want these key bindings to intervene. (This would break "ptterm" # for instance, which handles 'Keys.Any' in the user control itself.) ConditionalKeyBindings(all_bindings, buffer_has_focus), # Active, even when no buffer has been focused. load_mouse_bindings(), load_cpr_bindings(), ])
def create_application(self): # Default key bindings. open_in_editor_bindings = load_open_in_editor_bindings() prompt_bindings = create_prompt_bindings() self.app = Application( layout=self.create_layout(), style=merge_styles([ default_style(), DynamicStyle(lambda: self.style), ]), key_bindings=merge_key_bindings([ merge_key_bindings([ ConditionalKeyBindings( open_in_editor_bindings, to_filter(self.enable_open_in_editor) & has_focus(DEFAULT_BUFFER)), prompt_bindings ]), DynamicKeyBindings(lambda: self.extra_key_bindings), ]), editing_mode=self.editing_mode, reverse_vi_search_direction=True, on_render=self.on_render, input=self.input, output=self.output) self.app.mp = self
def activate_mode(self, name, force=False): if name not in self.modes: raise Exception("no such mode") mode = self.modes[name] if self.current_mode_name == mode.name and not force: return current_mode = self.current_mode if current_mode and current_mode.on_dectivated: current_mode.on_dectivated(self) self._current_mode = mode self._restore_settings() for name in self._fields: if name != "key_bindings": if hasattr(mode, name): setattr(self, name, getattr(mode, name)) self.key_bindings = merge_key_bindings([ DynamicKeyBindings(lambda: self.current_mode.prompt_key_bindings), merge_key_bindings([ m.key_bindings for m in self.modes.values() if m.key_bindings ]) ]) if mode.on_activated: mode.on_activated(self)
def _create_application(self, editing_mode, erase_when_done): """ Create the `Application` object. """ dyncond = self._dyncond # Default key bindings. auto_suggest_bindings = load_auto_suggest_bindings() open_in_editor_bindings = load_open_in_editor_bindings() prompt_bindings = self._create_prompt_bindings() # Create application application = Application( layout=self.layout, style=DynamicStyle(lambda: self.style), include_default_pygments_style=dyncond( 'include_default_pygments_style'), clipboard=DynamicClipboard(lambda: self.clipboard), key_bindings=merge_key_bindings([ merge_key_bindings([ auto_suggest_bindings, ConditionalKeyBindings( open_in_editor_bindings, dyncond('enable_open_in_editor') & has_focus(DEFAULT_BUFFER)), prompt_bindings ]), DynamicKeyBindings(lambda: self.key_bindings), ]), mouse_support=dyncond('mouse_support'), editing_mode=editing_mode, erase_when_done=erase_when_done, reverse_vi_search_direction=True, color_depth=lambda: self.color_depth, # I/O. input=self.input, output=self.output) # During render time, make sure that we focus the right search control # (if we are searching). - This could be useful if people make the # 'multiline' property dynamic. ''' def on_render(app): multiline = _true(self.multiline) current_control = app.layout.current_control if multiline: if current_control == search_buffer_control: app.layout.current_control = search_toolbar.control app.invalidate() else: if current_control == search_toolbar.control: app.layout.current_control = search_buffer_control app.invalidate() app.on_render += on_render ''' return application
def build_application(): layout = Layout(RootController()) def ensure_focus(_): """Ensures that at least one element on the screen is focused""" app = get_app() # prompt_toolkit's implementation of focusing is retarded # so this is the only way I found of 'making it work' # when switching screens or something prompt_toolkit doesn't recognize # the new focusable elements added to the screen. this will ensure # that at least one container/ui is marked as focusable so # the screen can be interacted with global global__default_target_focus # preferred element to be focused if global__default_target_focus: app.layout.focus(global__default_target_focus) global__default_target_focus = None # reset for next render app.invalidate() # trigger re-render elif len(app.layout.get_visible_focusable_windows()) == 0: focus_first_element() app.invalidate() # trigger re-render return Application(layout=layout, key_bindings=merge_key_bindings( [tab_bindings, exit_bindings]), full_screen=True, mouse_support=True, after_render=ensure_focus, style=root_style)
def __init__(self, **kwargs): ptk_args = kwargs.pop("ptk_args", {}) super().__init__(**kwargs) if ON_WINDOWS: winutils.enable_virtual_terminal_processing() self._first_prompt = True self.history = ThreadedHistory(PromptToolkitHistory()) ptk_args.setdefault("history", self.history) if not XSH.env.get("XONSH_COPY_ON_DELETE", False): disable_copy_on_deletion() if HAVE_SYS_CLIPBOARD: ptk_args.setdefault("clipboard", PyperclipClipboard()) self.prompter: PromptSession = PromptSession(**ptk_args) self.prompt_formatter = PTKPromptFormatter(self) self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self) ptk_bindings = self.prompter.app.key_bindings self.key_bindings = load_xonsh_bindings(ptk_bindings) self._overrides_deprecation_warning_shown = False # Store original `_history_matches` in case we need to restore it self._history_matches_orig = self.prompter.default_buffer._history_matches # This assumes that PromptToolkitShell is a singleton events.on_ptk_create.fire( prompter=self.prompter, history=self.history, completer=self.pt_completer, bindings=self.key_bindings, ) # Goes at the end, since _MergedKeyBindings objects do not have # an add() function, which is necessary for on_ptk_create events self.key_bindings = merge_key_bindings( [self.key_bindings, load_emacs_shift_selection_bindings()] )
def __init__(self, **kwargs): super().__init__(**kwargs) if ON_WINDOWS: winutils.enable_virtual_terminal_processing() self._first_prompt = True self.history = ThreadedHistory(PromptToolkitHistory()) self.prompter = PromptSession(history=self.history) self.prompt_formatter = PTKPromptFormatter(self.prompter) self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self) self.key_bindings = load_xonsh_bindings() # Store original `_history_matches` in case we need to restore it self._history_matches_orig = self.prompter.default_buffer._history_matches # This assumes that PromptToolkitShell is a singleton events.on_ptk_create.fire( prompter=self.prompter, history=self.history, completer=self.pt_completer, bindings=self.key_bindings, ) # Goes at the end, since _MergedKeyBindings objects do not have # an add() function, which is necessary for on_ptk_create events self.key_bindings = merge_key_bindings( [self.key_bindings, load_emacs_shift_selection_bindings()])
def __init__(self, show_message, **kwargs): self.show_message = show_message super().__init__(**kwargs) key_bindings = KeyBindings() handle = key_bindings.add # Readline-style bindings. handle("home")(get_by_name("beginning-of-line")) handle("end")(get_by_name("end-of-line")) handle("left")(get_by_name("backward-char")) handle("right")(get_by_name("forward-char")) @handle("up") def _(event: KeyPressEvent) -> None: event.current_buffer.auto_up(count=event.arg) @handle("down") def _(event: KeyPressEvent) -> None: event.current_buffer.auto_down(count=event.arg) self._default_bindings = merge_key_bindings( [ key_bindings, load_emacs_shift_selection_bindings() ])
def _create_key_bindings(self, current_window, other_controls): """ Create a `KeyBindings` object that merges the `KeyBindings` from the `UIControl` with all the parent controls and the global key bindings. """ key_bindings = [] # Collect key bindings from currently focused control and all parent # controls. Don't include key bindings of container parent controls. container = current_window while container is not None: kb = container.get_key_bindings() if kb is not None: key_bindings.append(kb) if container.is_modal(): break container = self.app.layout.get_parent(container) # Add App key bindings if self.app.key_bindings: key_bindings.append(self.app.key_bindings) # Add mouse bindings. key_bindings.append( ConditionalKeyBindings(self.app._page_navigation_bindings, self.app.enable_page_navigation_bindings)) key_bindings.append(self.app._default_bindings) # Reverse this list. The current control's key bindings should come # last. They need priority. key_bindings = key_bindings[::-1] return merge_key_bindings(key_bindings)
def choose_version(assets): '''choose a version from assets list''' versions = list(map(lambda item: item['version'], assets)) # print(versions) values = list(map(lambda item: (item, item), versions)) rdo = NewRadioList(values) def do_exit(event): # get_app().exit() event.app.exit(result=rdo.current_value) def do_up_down(event): print(event) pass bindings = KeyBindings() bindings.add('enter')(do_exit) app_bindings = merge_key_bindings([load_key_bindings(), bindings]) selected = Application(layout=Layout(rdo), key_bindings=app_bindings).run() if selected in versions: print('your choice is:', end=' ') # refer: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/examples/print-text/ansi.py print_formatted_text(ANSI('\x1b[91m{0}'.format(selected))) return selected else: print('canceled')
def _create_application(self, editing_mode, erase_when_done): prompt_bindings = self._create_prompt_bindings() search_mode_bindings = self._create_search_mode_bindings() application = Application( layout=self.layout, full_screen=True, key_bindings=merge_key_bindings([ merge_key_bindings([search_mode_bindings, prompt_bindings]), ]), color_depth=lambda: self.color_depth, input=self.input, output=self.output) return application
def load_page_navigation_bindings(): """ Load both the Vi and Emacs bindings for page navigation. """ return merge_key_bindings([ load_emacs_page_navigation_bindings(), load_vi_page_navigation_bindings(), ])
def load_page_navigation_bindings() -> KeyBindingsBase: """ Load both the Vi and Emacs bindings for page navigation. """ # Only enable when a `Buffer` is focused, otherwise, we would catch keys # when another widget is focused (like for instance `c-d` in a # ptterm.Terminal). return ConditionalKeyBindings( merge_key_bindings([ load_emacs_page_navigation_bindings(), load_vi_page_navigation_bindings(), ]), buffer_has_focus)
def _create_key_bindings( self, current_window: Window, other_controls: List[UIControl] ) -> KeyBindingsBase: """ Create a `KeyBindings` object that merges the `KeyBindings` from the `UIControl` with all the parent controls and the global key bindings. """ key_bindings = [] collected_containers = set() # Collect key bindings from currently focused control and all parent # controls. Don't include key bindings of container parent controls. container: Container = current_window while True: collected_containers.add(container) kb = container.get_key_bindings() if kb is not None: key_bindings.append(kb) if container.is_modal(): break parent = self.app.layout.get_parent(container) if parent is None: break else: container = parent # Include global bindings (starting at the top-model container). for c in walk(container): if c not in collected_containers: kb = c.get_key_bindings() if kb is not None: key_bindings.append(GlobalOnlyKeyBindings(kb)) # Add App key bindings if self.app.key_bindings: key_bindings.append(self.app.key_bindings) # Add mouse bindings. key_bindings.append( ConditionalKeyBindings( self.app._page_navigation_bindings, self.app.enable_page_navigation_bindings, ) ) key_bindings.append(self.app._default_bindings) # Reverse this list. The current control's key bindings should come # last. They need priority. key_bindings = key_bindings[::-1] return merge_key_bindings(key_bindings)
def _create_app(dialog: AnyContainer, style: Optional[BaseStyle]) -> Application[Any]: # Key bindings. bindings = KeyBindings() bindings.add("tab")(focus_next) bindings.add("s-tab")(focus_previous) return Application( layout=Layout(dialog), key_bindings=merge_key_bindings([load_key_bindings(), bindings]), mouse_support=True, style=style, full_screen=True, )
def _create_app(dialog, style): # Key bindings. bindings = KeyBindings() bindings.add('tab')(focus_next) bindings.add('s-tab')(focus_previous) return Application(layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=style, full_screen=True)
def _build_key_bindings(self): focussed = has_focus(self.system_buffer) # Emacs emacs_bindings = KeyBindings() handle = emacs_bindings.add @handle('escape', filter=focussed) @handle('c-g', filter=focussed) @handle('c-c', filter=focussed) def _(event): " Hide system prompt. " self.system_buffer.reset() event.app.layout.focus_previous() @handle('enter', filter=focussed) def _(event): " Run system command. " event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_previous() # Vi. vi_bindings = KeyBindings() handle = vi_bindings.add @handle('escape', filter=focussed) @handle('c-c', filter=focussed) def _(event): " Hide system prompt. " event.app.vi_state.input_mode = InputMode.NAVIGATION self.system_buffer.reset() event.app.layout.focus_previous() @handle('enter', filter=focussed) def _(event): " Run system command. " event.app.vi_state.input_mode = InputMode.NAVIGATION event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_previous() return merge_key_bindings([ ConditionalKeyBindings(emacs_bindings, emacs_mode), ConditionalKeyBindings(vi_bindings, vi_mode), ])
def _create_key_bindings(self, current_window: Window, other_controls: List[UIControl]) -> KeyBindingsBase: """ Create a `KeyBindings` object that merges the `KeyBindings` from the `UIControl` with all the parent controls and the global key bindings. """ key_bindings = [] collected_containers = set() # Collect key bindings from currently focused control and all parent # controls. Don't include key bindings of container parent controls. container: Container = current_window while True: collected_containers.add(container) kb = container.get_key_bindings() if kb is not None: key_bindings.append(kb) if container.is_modal(): break parent = self.app.layout.get_parent(container) if parent is None: break else: container = parent # Include global bindings (starting at the top-model container). for c in walk(container): if c not in collected_containers: kb = c.get_key_bindings() if kb is not None: key_bindings.append(GlobalOnlyKeyBindings(kb)) # Add App key bindings if self.app.key_bindings: key_bindings.append(self.app.key_bindings) # Add mouse bindings. key_bindings.append(ConditionalKeyBindings( self.app._page_navigation_bindings, self.app.enable_page_navigation_bindings)) key_bindings.append(self.app._default_bindings) # Reverse this list. The current control's key bindings should come # last. They need priority. key_bindings = key_bindings[::-1] return merge_key_bindings(key_bindings)
def _create_app(dialog: AnyContainer, style: Optional[BaseStyle]) -> Application[Any]: # Key bindings. bindings = KeyBindings() bindings.add('tab')(focus_next) bindings.add('s-tab')(focus_previous) return Application( layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=style, full_screen=True)
def _create_app(dialog, style): # Key bindings. bindings = KeyBindings() bindings.add('tab')(focus_next) bindings.add('s-tab')(focus_previous) return Application( layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=style, full_screen=True)
def __init__(self, **kwargs): super().__init__(**kwargs) if ON_WINDOWS: winutils.enable_virtual_terminal_processing() self._first_prompt = True self.history = ThreadedHistory(PromptToolkitHistory()) self.prompter = PromptSession(history=self.history) self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self) self.key_bindings = merge_key_bindings( [load_xonsh_bindings(), load_emacs_shift_selection_bindings()]) # Store original `_history_matches` in case we need to restore it self._history_matches_orig = self.prompter.default_buffer._history_matches # This assumes that PromptToolkitShell is a singleton events.on_ptk_create.fire( prompter=self.prompter, history=self.history, completer=self.pt_completer, bindings=self.key_bindings, )
def radiolist_dialog(title='', values=None, style=None, async_=False): # Add exit key binding. bindings = KeyBindings() @bindings.add('c-d') def exit_(event): """ Pressing Ctrl-d will exit the user interface. """ event.app.exit() radio_list = RadioListFast(values) application = Application( layout=Layout(HSplit([Label(title), radio_list])), key_bindings=merge_key_bindings([load_key_bindings(), bindings]), mouse_support=True, style=style, full_screen=False) if async_: return application.run_async() else: return application.run()
def _build_key_bindings(self): focused = has_focus(self.system_buffer) # Emacs emacs_bindings = KeyBindings() handle = emacs_bindings.add @handle('escape', filter=focused) @handle('c-g', filter=focused) @handle('c-c', filter=focused) def _(event): " Hide system prompt. " self.system_buffer.reset() event.app.layout.focus_last() @handle('enter', filter=focused) def _(event): " Run system command. " event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_last() # Vi. vi_bindings = KeyBindings() handle = vi_bindings.add @handle('escape', filter=focused) @handle('c-c', filter=focused) def _(event): " Hide system prompt. " event.app.vi_state.input_mode = InputMode.NAVIGATION self.system_buffer.reset() event.app.layout.focus_last() @handle('enter', filter=focused) def _(event): " Run system command. " event.app.vi_state.input_mode = InputMode.NAVIGATION event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_last() # Global bindings. (Listen to these bindings, even when this widget is # not focussed.) global_bindings = KeyBindings() handle = global_bindings.add @handle(Keys.Escape, '!', filter=~focused & emacs_mode, is_global=True) def _(event): " M-'!' will focus this user control. " event.app.layout.focus(self.window) @handle('!', filter=~focused & vi_mode & vi_navigation_mode, is_global=True) def _(event): " Focus. " event.app.vi_state.input_mode = InputMode.INSERT event.app.layout.focus(self.window) return merge_key_bindings([ ConditionalKeyBindings(emacs_bindings, emacs_mode), ConditionalKeyBindings(vi_bindings, vi_mode), ConditionalKeyBindings(global_bindings, self.enable_global_bindings), ])
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), )
from new_radio_list import NewRadioList library = 'jqueryui' resp = requests.get( 'https://api.cdnjs.com/libraries/{0}?fields=assets'.format(library)) if resp.ok: data = json.loads(resp.text) if isinstance(data, dict) and 'assets' in data: assets = data['assets'] versions = list(map(lambda item: item['version'], assets)) print(versions) values = list(map(lambda item: (item, item), versions)) rdo = NewRadioList(values) def do_exit(event): # get_app().exit() event.app.exit(result=rdo.current_value) def do_up_down(event): print(event) pass bindings = KeyBindings() bindings.add('enter')(do_exit) app_bindings = merge_key_bindings([load_key_bindings(), bindings]) selected = Application(layout=Layout(rdo), key_bindings=app_bindings).run() print('your choice is:', end=' ') # refer: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/examples/print-text/ansi.py print_formatted_text(ANSI('\x1b[91m{0}'.format(selected)))
def _create_application(self, editing_mode, erase_when_done): def dyncond(attr_name): """ Dynamically take this setting from this 'Prompt' class. `attr_name` represents an attribute name of this class. Its value can either be a boolean or a `Filter`. This returns something that can be used as either a `Filter` or `Filter`. """ @Condition def dynamic(): value = getattr(self, attr_name) return to_filter(value)() return dynamic # Create functions that will dynamically split the prompt. (If we have # a multiline prompt.) has_before_fragments, get_prompt_text_1, get_prompt_text_2 = \ _split_multiline_prompt(self._get_prompt) # Create buffers list. def accept(buff): """ Accept the content of the default buffer. This is called when the validation succeeds. """ self.app.set_result(buff.document.text) # Reset content before running again. self.app.pre_run_callables.append(buff.reset) default_buffer = Buffer( name=DEFAULT_BUFFER, # Make sure that complete_while_typing is disabled when # enable_history_search is enabled. (First convert to Filter, # to avoid doing bitwise operations on bool objects.) complete_while_typing=Condition( lambda: _true(self.complete_while_typing) and not _true( self.enable_history_search) and not self.complete_style == CompleteStyle.READLINE_LIKE), validate_while_typing=dyncond('validate_while_typing'), enable_history_search=dyncond('enable_history_search'), validator=DynamicValidator(lambda: self.validator), completer=ThreadedCompleter( completer=DynamicCompleter(lambda: self.completer), in_thread=dyncond('complete_in_thread'), ), history=DynamicHistory(lambda: self.history), auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest), accept_handler=accept, get_tempfile_suffix=lambda: self.tempfile_suffix) search_buffer = Buffer(name=SEARCH_BUFFER) # Create processors list. input_processor = merge_processors([ ConditionalProcessor( # By default, only highlight search when the search # input has the focus. (Note that this doesn't mean # there is no search: the Vi 'n' binding for instance # still allows to jump to the next match in # navigation mode.) HighlightSearchProcessor(preview_search=True), has_focus(search_buffer)), HighlightSelectionProcessor(), ConditionalProcessor(AppendAutoSuggestion(), has_focus(default_buffer) & ~is_done), ConditionalProcessor(PasswordProcessor(), dyncond('is_password')), DisplayMultipleCursors(), # Users can insert processors here. DynamicProcessor(lambda: self.extra_input_processor), # For single line mode, show the prompt before the input. ConditionalProcessor( merge_processors([ BeforeInput(get_prompt_text_2), ShowArg(), ]), ~dyncond('multiline')) ]) # Create bottom toolbars. bottom_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar', dont_extend_height=True, height=Dimension(min=1)), filter=~is_done & renderer_height_is_known & Condition(lambda: self.bottom_toolbar is not None)) search_toolbar = SearchToolbar( search_buffer, get_search_state=lambda: default_buffer_control.get_search_state()) search_buffer_control = BufferControl(buffer=search_buffer, input_processor=merge_processors( [ ReverseSearchProcessor(), ShowArg(), ])) system_toolbar = SystemToolbar() def get_search_buffer_control(): " Return the UIControl to be focused when searching start. " if _true(self.multiline): return search_toolbar.control else: return search_buffer_control default_buffer_control = BufferControl( buffer=default_buffer, get_search_buffer_control=get_search_buffer_control, input_processor=input_processor, lexer=DynamicLexer(lambda: self.lexer), preview_search=True) default_buffer_window = Window( default_buffer_control, height=self._get_default_buffer_control_height, left_margins=[ # In multiline mode, use the window margin to display # the prompt and continuation fragments. ConditionalMargin( PromptMargin(get_prompt_text_2, self._get_continuation), filter=dyncond('multiline'), ) ], wrap_lines=dyncond('wrap_lines')) @Condition def multi_column_complete_style(): return self.complete_style == CompleteStyle.MULTI_COLUMN # Build the layout. layout = HSplit([ # The main input, with completion menus floating on top of it. FloatContainer( HSplit([ ConditionalContainer( Window(FormattedTextControl(get_prompt_text_1), dont_extend_height=True), Condition(has_before_fragments)), ConditionalContainer( default_buffer_window, Condition(lambda: get_app().layout.current_control != search_buffer_control), ), ConditionalContainer( Window(search_buffer_control), Condition(lambda: get_app().layout.current_control == search_buffer_control), ), ]), [ # Completion menus. Float(xcursor=True, ycursor=True, content=CompletionsMenu( max_height=16, scroll_offset=1, extra_filter=has_focus(default_buffer) & ~multi_column_complete_style)), Float(xcursor=True, ycursor=True, content=MultiColumnCompletionsMenu( show_meta=True, extra_filter=has_focus(default_buffer) & multi_column_complete_style)), # The right prompt. Float(right=0, top=0, hide_when_covering_content=True, content=_RPrompt(lambda: self.rprompt)), ]), ConditionalContainer(ValidationToolbar(), filter=~is_done), ConditionalContainer(system_toolbar, dyncond('enable_system_prompt') & ~is_done), # In multiline mode, we use two toolbars for 'arg' and 'search'. ConditionalContainer( Window(FormattedTextControl(self._get_arg_text), height=1), dyncond('multiline') & has_arg), ConditionalContainer(search_toolbar, dyncond('multiline') & ~is_done), bottom_toolbar, ]) # Default key bindings. auto_suggest_bindings = load_auto_suggest_bindings() open_in_editor_bindings = load_open_in_editor_bindings() prompt_bindings = self._create_prompt_bindings() # Create application application = Application( layout=Layout(layout, default_buffer_window), style=DynamicStyle(lambda: self.style), include_default_pygments_style=dyncond( 'include_default_pygments_style'), clipboard=DynamicClipboard(lambda: self.clipboard), key_bindings=merge_key_bindings([ merge_key_bindings([ auto_suggest_bindings, ConditionalKeyBindings( open_in_editor_bindings, dyncond('enable_open_in_editor') & has_focus(DEFAULT_BUFFER)), prompt_bindings ]), ConditionalKeyBindings( system_toolbar.get_global_key_bindings(), dyncond('enable_system_prompt')), DynamicKeyBindings(lambda: self.extra_key_bindings), ]), mouse_support=dyncond('mouse_support'), editing_mode=editing_mode, erase_when_done=erase_when_done, reverse_vi_search_direction=True, # I/O. input=self.input, output=self.output) # During render time, make sure that we focus the right search control # (if we are searching). - This could be useful if people make the # 'multiline' property dynamic. ''' def on_render(app): multiline = _true(self.multiline) current_control = app.layout.current_control if multiline: if current_control == search_buffer_control: app.layout.current_control = search_toolbar.control app.invalidate() else: if current_control == search_toolbar.control: app.layout.current_control = search_buffer_control app.invalidate() app.on_render += on_render ''' return application, default_buffer, default_buffer_control
@kb.add('tab', filter=(~has_completions) & ~has_focus(input_field)) def _(event: KeyPressEvent): event.app.layout.focus_next() @kb.add('s-tab') def _(event: KeyPressEvent): event.app.layout.focus_previous() @kb.add('enter', filter=has_focus(input_field)) def _(event: KeyPressEvent): input_field.add_history(input_field.text) input_field.text = '' text = 'hello' output_field.buffer.document = Document(text=text, cursor_position=len(text)) @kb.add('c-f', filter=has_focus(output_field)) def _(event: KeyPressEvent): start_search(output_field.control) global_kb = merge_key_bindings([ kb, load_auto_suggest_bindings(), load_mouse_bindings(), load_vi_bindings() ])
def _build_key_bindings(self): focused = has_focus(self.system_buffer) # Emacs emacs_bindings = KeyBindings() handle = emacs_bindings.add @handle('escape', filter=focused) @handle('c-g', filter=focused) @handle('c-c', filter=focused) def _(event): " Hide system prompt. " self.system_buffer.reset() event.app.layout.focus_last() @handle('enter', filter=focused) def _(event): " Run system command. " event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_last() # Vi. vi_bindings = KeyBindings() handle = vi_bindings.add @handle('escape', filter=focused) @handle('c-c', filter=focused) def _(event): " Hide system prompt. " event.app.vi_state.input_mode = InputMode.NAVIGATION self.system_buffer.reset() event.app.layout.focus_last() @handle('enter', filter=focused) def _(event): " Run system command. " event.app.vi_state.input_mode = InputMode.NAVIGATION event.app.run_system_command( self.system_buffer.text, display_before_text=self._get_display_before_text()) self.system_buffer.reset(append_to_history=True) event.app.layout.focus_last() # Global bindings. (Listen to these bindings, even when this widget is # not focussed.) global_bindings = KeyBindings() handle = global_bindings.add @handle(Keys.Escape, '!', filter= ~focused & emacs_mode, is_global=True) def _(event): " M-'!' will focus this user control. " event.app.layout.focus(self.window) @handle('!', filter=~focused & vi_mode & vi_navigation_mode, is_global=True) def _(event): " Focus. " event.app.vi_state.input_mode = InputMode.INSERT event.app.layout.focus(self.window) return merge_key_bindings([ ConditionalKeyBindings(emacs_bindings, emacs_mode), ConditionalKeyBindings(vi_bindings, vi_mode), ConditionalKeyBindings(global_bindings, self.enable_global_bindings), ])
def show_dialog(questions, title, confirm, cancel): handlers = [] layouts = [] for q in questions: handler = get_instance(q) l = handler.get_layout() l.align = HorizontalAlign.JUSTIFY layouts.append(l) handlers.append(handler) def ok_handler(): result = dict() for handler in handlers: result.update(handler.get_answer()) get_app().exit(result=result) dialog = Dialog(title=title, body=HSplit(layouts, padding=1), buttons=[ Button(text=confirm, handler=ok_handler), Button(text=cancel, handler=lambda: get_app().exit()), ], with_background=True) # Key bindings. bindings = KeyBindings() app = Application(layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=for_dialog(), full_screen=True) size = app.renderer.output.get_size() container = app.layout.container height = container.preferred_height(size.columns, size.rows).preferred if height > size.rows: message_dialog(title='Too many questions', text='Cannot render a {} rows dialog in a ' '{} rows screen: too many questions!'.format( height, size.rows), ok_text='Got it!') return while True: validation_errors = [] answers = app.run() if answers is None: return for handler in handlers: if not handler.is_valid(): for msg in handler.errors: validation_errors.append('{}: {}'.format( handler.get_variable_name(), msg)) if not validation_errors: return answers show_error_dialog(validation_errors)
def _create_application(self, editing_mode, erase_when_done): """ Create the `Application` object. """ dyncond = self._dyncond # Default key bindings. auto_suggest_bindings = load_auto_suggest_bindings() open_in_editor_bindings = load_open_in_editor_bindings() prompt_bindings = self._create_prompt_bindings() # Create application application = Application( layout=self.layout, style=DynamicStyle(lambda: self.style), style_transformation=merge_style_transformations([ DynamicStyleTransformation(lambda: self.style_transformation), ConditionalStyleTransformation( SwapLightAndDarkStyleTransformation(), dyncond('swap_light_and_dark_colors'), ), ]), include_default_pygments_style=dyncond('include_default_pygments_style'), clipboard=DynamicClipboard(lambda: self.clipboard), key_bindings=merge_key_bindings([ merge_key_bindings([ auto_suggest_bindings, ConditionalKeyBindings(open_in_editor_bindings, dyncond('enable_open_in_editor') & has_focus(DEFAULT_BUFFER)), prompt_bindings ]), DynamicKeyBindings(lambda: self.key_bindings), ]), mouse_support=dyncond('mouse_support'), editing_mode=editing_mode, erase_when_done=erase_when_done, reverse_vi_search_direction=True, color_depth=lambda: self.color_depth, # I/O. input=self.input, output=self.output) # During render time, make sure that we focus the right search control # (if we are searching). - This could be useful if people make the # 'multiline' property dynamic. ''' def on_render(app): multiline = is_true(self.multiline) current_control = app.layout.current_control if multiline: if current_control == search_buffer_control: app.layout.current_control = search_toolbar.control app.invalidate() else: if current_control == search_toolbar.control: app.layout.current_control = search_buffer_control app.invalidate() app.on_render += on_render ''' return application
def show_dialog(questions, title, confirm, cancel): handlers = [] for q in questions: handler = get_handlers_registry().get_handler(q, questions, None, mode=Mode.DIALOG) handlers.append(handler) def ok_handler(): result = dict() for handler in handlers: result.update(handler.get_answer()) get_app().exit(result=result) dialog = Dialog(title=title, body=HSplit([h.get_layout() for h in handlers], padding=1), buttons=[ Button(text=confirm, handler=ok_handler), Button(text=cancel, handler=lambda: get_app().exit()), ], with_background=True) # Key bindings. bindings = KeyBindings() bindings.add('tab')(focus_next) bindings.add('s-tab')(focus_previous) app = Application(layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=get_theme_manager().get_current_style(), full_screen=True) size = app.renderer.output.get_size() container = app.layout.container height = container.preferred_height(size.columns, size.rows).preferred if height > size.rows: message_dialog(title='Too many questions', text='Cannot render a {} rows dialog in a ' '{} rows screen: too many questions!'.format( height, size.rows), ok_text='Got it!') return while True: validation_errors = [] answers = app.run() if answers is None: return for handler in handlers: for msg in handler.apply_validators(): validation_errors.append('{}: {}'.format( handler.get_variable_name(), msg)) if not validation_errors: return answers show_error_dialog(validation_errors)