""" show_status_bar = True current_path = None def get_statusbar_text(): return ' Press Ctrl-C to open menu. ' def get_statusbar_right_text(): return ' {}:{} '.format( text_field.document.cursor_position_row + 1, text_field.document.cursor_position_col + 1) search_toolbar = SearchToolbar() text_field = TextArea( lexer=DynamicLexer( lambda: PygmentsLexer.from_filename( ApplicationState.current_path or '.txt', sync_from_start=False)), scrollbar=True, line_numbers=True, search_field=search_toolbar, ) class TextInputDialog(object): def __init__(self, title='', label_text='', completer=None): self.future = Future()
def create_application(): def get_statusbar_text(): return "Ctrl-C: Close. Ctrl-E: Execute. Ctrl-S: Stop music. F2: Open Menu. " def get_statusbar_right_text(): return " {}:{} ".format( text_field.document.cursor_position_row + 1, text_field.document.cursor_position_col + 1, ) search_toolbar = SearchToolbar() text_field = TextArea( lexer=PygmentsLexer.from_filename('.mkl', sync_from_start=False), completer=VariableCompleter(ApplicationState.context), scrollbar=True, line_numbers=True, search_field=search_toolbar, ) class TextInputDialog: def __init__(self, title="", label_text="", completer=None): self.future = Future() def accept_text(buf): get_app().layout.focus(ok_button) buf.complete_state = None return True def accept(): self.future.set_result(self.text_area.text) def cancel(): self.future.set_result(None) self.text_area = TextArea( completer=completer, multiline=False, width=D(preferred=40), accept_handler=accept_text, ) ok_button = Button(text="OK", handler=accept) cancel_button = Button(text="Cancel", handler=cancel) self.dialog = Dialog( title=title, body=HSplit([Label(text=label_text), self.text_area]), buttons=[ok_button, cancel_button], width=D(preferred=80), modal=True, ) def __pt_container__(self): return self.dialog class MessageDialog: def __init__(self, title, text): self.future = Future() def set_done(): self.future.set_result(None) ok_button = Button(text="OK", handler=(lambda: set_done())) 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 body = HSplit([ text_field, search_toolbar, ConditionalContainer( content=VSplit( [ Window(FormattedTextControl(get_statusbar_text), style="class:status"), Window( FormattedTextControl(get_statusbar_right_text), style="class:status.right", width=9, align=WindowAlign.RIGHT, ), ], height=1, ), filter=Condition(lambda: ApplicationState.show_status_bar), ), ]) # Global key bindings. bindings = KeyBindings() @bindings.add("f2") def _(event): " Focus menu. " event.app.layout.focus(root_container.window) # # Handlers for menu items. # def do_open_file(): async def coroutine(): open_dialog = TextInputDialog( title="Open file", label_text="Enter the path of a file:", completer=PathCompleter(), ) path = await show_dialog_as_float(open_dialog) ApplicationState.current_path = path if path is not None: try: with open(path, "rb") as f: text_field.text = f.read().decode("utf-8", errors="ignore") except IOError as e: show_message("Error", "{}".format(e)) ensure_future(coroutine()) def do_about(): show_message("About", "Text editor demo.\nCreated by Jonathan Slenders.") def show_message(title, text): async def coroutine(): dialog = MessageDialog(title, text) await show_dialog_as_float(dialog) ensure_future(coroutine()) async def show_dialog_as_float(dialog): " Coroutine. " float_ = Float(content=dialog) root_container.floats.insert(0, float_) app = get_app() focused_before = app.layout.current_window app.layout.focus(dialog) result = await dialog.future app.layout.focus(focused_before) if float_ in root_container.floats: root_container.floats.remove(float_) return result @bindings.add('c-n') def do_new_file(event=None): text_field.text = "" @bindings.add('c-c') def do_exit(event=None): get_app().exit() def do_time_date(): text = datetime.datetime.now().isoformat() text_field.buffer.insert_text(text) def do_go_to(): async def coroutine(): dialog = TextInputDialog(title="Go to line", label_text="Line number:") line_number = await show_dialog_as_float(dialog) try: line_number = int(line_number) except ValueError: show_message("Invalid line number") else: text_field.buffer.cursor_position = text_field.buffer.document.translate_row_col_to_index( line_number - 1, 0) ensure_future(coroutine()) def do_undo(): text_field.buffer.undo() def do_cut(): data = text_field.buffer.cut_selection() get_app().clipboard.set_data(data) def do_copy(): data = text_field.buffer.copy_selection() get_app().clipboard.set_data(data) def do_delete(): text_field.buffer.cut_selection() def do_find(): start_search(text_field.control) def do_find_next(): search_state = get_app().current_search_state cursor_position = text_field.buffer.get_search_position( search_state, include_current_position=False) text_field.buffer.cursor_position = cursor_position def do_paste(): text_field.buffer.paste_clipboard_data(get_app().clipboard.get_data()) def do_select_all(): text_field.buffer.cursor_position = 0 text_field.buffer.start_selection() text_field.buffer.cursor_position = len(text_field.buffer.text) @bindings.add("c-e") def do_eval(event=None): if ApplicationState.context is None or ApplicationState.player is None: show_message("Error", "Cannot evaluate because no context is defined") return code = text_field.buffer.text try: script = ApplicationState.context.script now = ApplicationState.player.get_time() ctx = ApplicationState.context.fork(cursor=now) val = script.eval(code, context=ctx) if val is not None and isinstance(val, Music): pl = InteractivePlayer(lambda: val.expand(ctx), ApplicationState.player, realtime=True) ApplicationState.interactive_players.append(pl) create_task(pl.start()) except BaseException as e: if hasattr(e, 'message'): show_message("Eval Error", str(cast(Any, e).message)) else: show_message("Eval Error", str(e)) @bindings.add("c-s") def do_mute_players(event=None): for p in ApplicationState.interactive_players: create_task(p.stop()) ApplicationState.interactive_players = [] def do_status_bar(): ApplicationState.show_status_bar = not ApplicationState.show_status_bar # # The menu container. # root_container = MenuContainer( body=body, menu_items=[ MenuItem( "File", children=[ MenuItem("New...", handler=do_new_file), MenuItem("Open...", handler=do_open_file), MenuItem("Save"), MenuItem("Save as..."), MenuItem("-", disabled=True), MenuItem("Exit", handler=do_exit), ], ), MenuItem( "Edit", children=[ MenuItem("Undo", handler=do_undo), MenuItem("Cut", handler=do_cut), MenuItem("Copy", handler=do_copy), MenuItem("Paste", handler=do_paste), MenuItem("Delete", handler=do_delete), MenuItem("-", disabled=True), MenuItem("Find", handler=do_find), MenuItem("Find next", handler=do_find_next), MenuItem("Replace"), MenuItem("Go To", handler=do_go_to), MenuItem("Select All", handler=do_select_all), MenuItem("Time/Date", handler=do_time_date), ], ), MenuItem("View", children=[ MenuItem("Status Bar", handler=do_status_bar), ]), MenuItem("Info", children=[ MenuItem("About", handler=do_about), ]), ], floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), ], key_bindings=bindings, ) style = Style.from_dict({ "status": "reverse", "shadow": "bg:#440044", }) layout = Layout(root_container, focused_element=text_field) application = Application( layout=layout, enable_page_navigation_bindings=True, style=style, mouse_support=True, full_screen=True, ) return application, text_field
def main(): # The layout. search_field = SearchToolbar() # For reverse search. output_field = TextArea(style="class:output-field", text=help_text) input_field = TextArea( height=1, prompt=">>> ", style="class:input-field", multiline=False, wrap_lines=False, search_field=search_field, ) container = HSplit( [ output_field, Window(height=1, char="-", style="class:line"), input_field, search_field, ] ) # Attach accept handler to the input field. We do this by assigning the # handler to the `TextArea` that we created earlier. it is also possible to # pass it to the constructor of `TextArea`. # NOTE: It's better to assign an `accept_handler`, rather then adding a # custom ENTER key binding. This will automatically reset the input # field and add the strings to the history. def accept(buff): # Evaluate "calculator" expression. try: output = "\n\nIn: {}\nOut: {}".format( input_field.text, eval(input_field.text) ) # Don't do 'eval' in real code! except BaseException as e: output = "\n\n{}".format(e) new_text = output_field.text + output # Add text to output buffer. output_field.buffer.document = Document( text=new_text, cursor_position=len(new_text) ) input_field.accept_handler = accept # The key bindings. kb = KeyBindings() @kb.add("c-c") @kb.add("c-q") def _(event): "Pressing Ctrl-Q or Ctrl-C will exit the user interface." event.app.exit() # Style. style = Style( [ ("output-field", "bg:#000044 #ffffff"), ("input-field", "bg:#000000 #ffffff"), ("line", "#004400"), ] ) # Run application. application = Application( layout=Layout(container, focused_element=input_field), key_bindings=kb, style=style, mouse_support=True, full_screen=True, ) application.run()
"class:status.position", "{}:{}".format( text_area.document.cursor_position_row + 1, text_area.document.cursor_position_col + 1, ), ), ("class:status", " - Press "), ("class:status.key", "Ctrl-C"), ("class:status", " to exit, "), ("class:status.key", "/"), ("class:status", " for searching."), ] search_field = SearchToolbar( text_if_not_searching=[("class:not-searching", "Press '/' to start searching.")]) text_area = TextArea( text=text, read_only=True, scrollbar=True, line_numbers=True, search_field=search_field, lexer=PygmentsLexer(PythonLexer), ) root_container = HSplit([ # The top toolbar. Window( content=FormattedTextControl(get_statusbar_text),
def __init__(self, my_app: "sqlApp") -> None: self.my_app = my_app self.search_field = SearchToolbar() history_file = config_location() + 'history' ensure_dir_exists(history_file) hist = ThreadedHistory(FileHistory(expanduser(history_file))) self.input_buffer = Buffer( name="defaultbuffer", tempfile_suffix=".py", multiline=MultilineFilter(self.my_app), history=hist, completer=ThreadedCompleter(self.my_app.completer), auto_suggest=ThreadedAutoSuggest(AutoSuggestFromHistory()), complete_while_typing=Condition( lambda: self.my_app.active_conn is not None)) main_win_control = BufferControl( buffer=self.input_buffer, lexer=PygmentsLexer(SqlLexer), search_buffer_control=self.search_field.control, include_default_input_processors=False, input_processors=[AppendAutoSuggestion()], preview_search=True) self.main_win = Window( main_win_control, height=( lambda: (None if get_app().is_done else (Dimension(min=self.my_app.min_num_menu_lines) if not self.my_app.show_preview else Dimension( min=self.my_app.min_num_menu_lines, preferred=180)))), get_line_prefix=partial(sql_line_prefix, my_app=self.my_app), scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4)) preview_element = PreviewElement(self.my_app) self.lprompt = login_prompt(self.my_app) self.preview = preview_element.create_container() self.disconnect_dialog = disconnect_dialog(self.my_app) container = HSplit([ VSplit([ FloatContainer( content=HSplit([ self.main_win, self.search_field, ]), floats=[ Float( bottom=1, left=1, right=0, content=sql_sidebar_help(self.my_app), ), Float(content=self.lprompt), Float(content=self.preview, ), preview_element.create_completion_float(), Float(content=self.disconnect_dialog, ), Float(left=2, bottom=1, content=exit_confirmation(self.my_app)), Float(xcursor=True, ycursor=True, transparent=True, content=CompletionsMenu(scroll_offset=1, max_height=16, extra_filter=has_focus( self.input_buffer))) ]), ConditionalContainer( content=sql_sidebar(self.my_app), filter=ShowSidebar(self.my_app) & ~is_done, ) ]), VSplit([ status_bar(self.my_app), show_sidebar_button_info(self.my_app) ]) ]) def accept(buff): app = get_app() app.exit(result=["non-preview", buff.text]) app.pre_run_callables.append(buff.reset) return True self.input_buffer.accept_handler = accept self.layout = Layout(container, focused_element=self.main_win)
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), )
def _(event): 'Help' do_help() @BINDINGS.add('f11') def _(event): 'Help' do_about() # Handlers # -------- SEARCH_TOOLBAR = SearchToolbar() TEXT_FIELD = TextArea( lexer=DynamicLexer( lambda: PygmentsLexer.from_filename( ApplicationState.current_path or '.txt', sync_from_start=False ) ), scrollbar=False, line_numbers=True, wrap_lines=True, search_field=SEARCH_TOOLBAR, ) TITLE = Window( height=1, content=FormattedTextControl('cli-pto'), align=WindowAlign.CENTER,