def __init__(self, app=None, show=True, height=Dimension(preferred=60), width=Dimension(preferred=1)): #80? self.app = app self.show = show self.basename = None self.filename = None self.current_line = -1 self.handle_source_change = False self.lexer = None self.buffer = Buffer(document=Document(), multiline=True) # TODO: Intelligent readonly lambda self.control = BufferControl(self.buffer, focusable=True, lexer=DynamicLexer(lambda: self.lexer), focus_on_click=True) self.window = Window(content=self.control, height=height, width=width, wrap_lines=False, left_margins=[NumberedMargin()], scroll_offsets = ScrollOffsets(top=5, bottom=40), get_line_prefix=self._get_line_prefix) self.info = InfoLine(text='', width=240) self.container = ConditionalContainer( content=HSplit([self.info.get_ui(), self.window]), filter=Condition(lambda: self.show))
def _create_application(self, color_depth): """ Create an `Application` instance. """ return Application( input=self.input, output=self.output, layout=create_layout( 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), key_bindings=merge_key_bindings([ load_python_bindings(self), load_sidebar_bindings(self), load_confirm_exit_bindings(self), # Extra key bindings should not be active when the sidebar is visible. ConditionalKeyBindings( self.extra_key_bindings, Condition(lambda: not self.show_sidebar)) ]), color_depth=color_depth, paste_mode=Condition(lambda: self.paste_mode), mouse_support=Condition(lambda: self.enable_mouse_support), style=DynamicStyle(lambda: self._current_style), include_default_pygments_style=False, reverse_vi_search_direction=True)
def __init__(self): super().__init__() self.paused = True self.app_thread = threading.Thread(target=self.start_gui, args=(asyncio.get_event_loop(),)) self.frame_history = FrameHistory() self.search_toolbar = SearchToolbar( text_if_not_searching=[("class:not-searching", "Press '/' to start searching.")] ) def get_view_file(): if len(self.frame_history.history) > 0: return self.frame_history.hist_frame.filename return ".py" self.text_area = TextArea( lexer=DynamicLexer( lambda: PygmentsLexer.from_filename( get_view_file(), sync_from_start=False ) ), search_field=self.search_toolbar, scrollbar=True, line_numbers=True, ) self.container = HSplit( [ self.text_area, self.search_toolbar, ] ) kb = KeyBindings() @kb.add("c-q") def _(event: KeyPressEvent): self.paused = False self._quit() @kb.add("c-n") def _(event): self.set_next(self.frame_history.exec_frame.raw_frame) self.paused = False # allow another frame to be processed self.app = Application( full_screen=True, layout=Layout(container=self.container), key_bindings=kb, ) self.app.loop = asyncio.get_event_loop()
def _create_layout(self): """ Create `Layout` for this prompt. """ dyncond = self._dyncond # 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) default_buffer = self.default_buffer search_buffer = self.search_buffer # Create processors list. all_input_processors = [ HighlightIncrementalSearchProcessor(), HighlightSelectionProcessor(), ConditionalProcessor(AppendAutoSuggestion(), has_focus(default_buffer) & ~is_done), ConditionalProcessor(PasswordProcessor(), dyncond('is_password')), DisplayMultipleCursors(), # Users can insert processors here. DynamicProcessor( lambda: merge_processors(self.input_processors or [])), # 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, ignore_case=dyncond('search_ignore_case')) search_buffer_control = SearchBufferControl( buffer=search_buffer, input_processors=[ ReverseSearchProcessor(), ShowArg(), ], ignore_case=dyncond('search_ignore_case')) system_toolbar = SystemToolbar( enable_global_bindings=dyncond('enable_system_prompt')) 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, search_buffer_control=get_search_buffer_control, input_processors=all_input_processors, include_default_input_processors=False, 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, ]) return Layout(layout, default_buffer_window)
def __init__(self, text='', multiline=True, password=False, lexer=None, auto_suggest=None, completer=None, complete_while_typing=True, accept_handler=None, history=None, focusable=True, focus_on_click=False, wrap_lines=True, read_only=False, width=None, height=None, dont_extend_height=False, dont_extend_width=False, line_numbers=False, get_line_prefix=None, scrollbar=False, style='', search_field=None, preview_search=True, prompt='', input_processors=None, max_line_count=1000, initial_text="", align=WindowAlign.LEFT): assert isinstance(text, six.text_type) assert search_field is None or isinstance(search_field, SearchToolbar) if search_field is None: search_control = None elif isinstance(search_field, SearchToolbar): search_control = search_field.control if input_processors is None: input_processors = [] # Writeable attributes. self.completer = completer self.complete_while_typing = complete_while_typing self.lexer = lexer self.auto_suggest = auto_suggest self.read_only = read_only self.wrap_lines = wrap_lines self.max_line_count = max_line_count self.buffer = CustomBuffer( document=Document(text, 0), multiline=multiline, read_only=Condition(lambda: is_true(self.read_only)), completer=DynamicCompleter(lambda: self.completer), complete_while_typing=Condition( lambda: is_true(self.complete_while_typing)), auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest), accept_handler=accept_handler, history=history) self.control = BufferControl( buffer=self.buffer, lexer=DynamicLexer(lambda: self.lexer), input_processors=[ ConditionalProcessor( AppendAutoSuggestion(), has_focus(self.buffer) & ~is_done), ConditionalProcessor( processor=PasswordProcessor(), filter=to_filter(password) ), BeforeInput(prompt, style='class:text-area.prompt'), ] + input_processors, search_buffer_control=search_control, preview_search=preview_search, focusable=focusable, focus_on_click=focus_on_click) if multiline: if scrollbar: right_margins = [ScrollbarMargin(display_arrows=True)] else: right_margins = [] if line_numbers: left_margins = [NumberedMargin()] else: left_margins = [] else: left_margins = [] right_margins = [] style = 'class:text-area ' + style self.window = Window( height=height, width=width, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, content=self.control, style=style, wrap_lines=Condition(lambda: is_true(self.wrap_lines)), left_margins=left_margins, right_margins=right_margins, get_line_prefix=get_line_prefix, align=align) self.log_lines: Deque[str] = deque() self.log(initial_text)
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 accept_text(): get_app().layout.focus(ok_button) self.text_area.buffer.complete_state = None
def __init__( self, get_globals=None, get_locals=None, history_filename=None, vi_mode=False, input=None, output=None, color_depth=None, # For internal use. extra_key_bindings=None, _completer=None, _validator=None, _lexer=None, _extra_buffer_processors=None, _extra_layout_body=None, _extra_toolbars=None, _input_buffer_height=None): self.get_globals = get_globals or (lambda: {}) self.get_locals = get_locals or self.get_globals self._completer = _completer or PythonCompleter( self.get_globals, self.get_locals) self._validator = _validator or PythonValidator( self.get_compiler_flags) self._lexer = _lexer or PygmentsLexer(PythonLexer) 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.show_signature = False self.show_docstring = False self.show_meta_enter_message = True self.completion_visualisation = CompletionVisualisation.MULTI_COLUMN self.completion_menu_scroll_offset = 1 self.show_line_numbers = False self.show_status_bar = True self.wrap_lines = True self.complete_while_typing = True self.paste_mode = False # When True, don't insert whitespace after newline. self.confirm_exit = True # Ask for confirmation when Control-D is pressed. self.accept_input_on_enter = 2 # Accept when pressing Enter 'n' times. # 'None' means that meta-enter is always required. self.enable_open_in_editor = True self.enable_system_bindings = True self.enable_input_validation = True self.enable_auto_suggest = False self.enable_mouse_support = False self.enable_history_search = 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 = True self.swap_light_and_dark = False self.highlight_matching_parenthesis = False self.show_sidebar = False # Currently show the sidebar. self.show_sidebar_help = True # When the sidebar is visible, also show the help text. self.show_exit_confirmation = False # Currently show 'Do you really want to exit?' self.terminal_title = None # The title to be displayed in the terminal. (None or string.) self.exit_message = 'Do you really want to exit?' self.insert_blank_line_after_output = True # (For the REPL.) # The buffers. self.default_buffer = self._create_buffer() self.search_buffer = Buffer() self.docstring_buffer = Buffer(read_only=True) # Tokens to be shown at the prompt. self.prompt_style = 'classic' # The currently active style. self.all_prompt_styles = { # Styles selectable from the menu. '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 = get_all_code_styles() self.ui_styles = get_all_ui_styles() self._current_code_style_name = 'default' self._current_ui_style_name = 'default' if is_windows(): self._current_code_style_name = 'win32' self._current_style = self._generate_style() self.color_depth = color_depth or ColorDepth.default() self.max_brightness = 1.0 self.min_brightness = 0.0 # Options to be configurable from the sidebar. self.options = self._create_options() self.selected_option_index = 0 #: Incremeting integer counting the current statement. self.current_statement_index = 1 # Code signatures. (This is set asynchronously after a timeout.) self.signatures = [] # Boolean indicating whether we have a signatures thread running. # (Never run more than one at the same time.) self._get_signatures_thread_running = False self.output = output or create_output() self.input = input or create_input(sys.stdin) 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() if vi_mode: self.app.editing_mode = EditingMode.VI
def __init__(self, text: str = '', multiline: FilterOrBool = True, password: FilterOrBool = False, lexer: Optional[Lexer] = None, auto_suggest: Optional[AutoSuggest] = None, completer: Optional[Completer] = None, complete_while_typing: FilterOrBool = True, accept_handler: Optional[BufferAcceptHandler] = None, history: Optional[History] = None, focusable: FilterOrBool = True, focus_on_click: FilterOrBool = False, wrap_lines: FilterOrBool = True, read_only: FilterOrBool = False, width: AnyDimension = None, height: AnyDimension = None, dont_extend_height: FilterOrBool = False, dont_extend_width: FilterOrBool = False, line_numbers: bool = False, get_line_prefix: Optional[GetLinePrefixCallable] = None, scrollbar: bool = False, style: str = '', search_field: Optional[SearchToolbar] = None, preview_search: FilterOrBool = True, prompt: AnyFormattedText = '', input_processors: Optional[List[Processor]] = None) -> None: if search_field is None: search_control = None elif isinstance(search_field, SearchToolbar): search_control = search_field.control if input_processors is None: input_processors = [] # Writeable attributes. self.completer = completer self.complete_while_typing = complete_while_typing self.lexer = lexer self.auto_suggest = auto_suggest self.read_only = read_only self.wrap_lines = wrap_lines self.buffer = Buffer( document=Document(text, 0), multiline=multiline, read_only=Condition(lambda: is_true(self.read_only)), completer=DynamicCompleter(lambda: self.completer), complete_while_typing=Condition( lambda: is_true(self.complete_while_typing)), auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest), accept_handler=accept_handler, history=history) self.control = BufferControl( buffer=self.buffer, lexer=DynamicLexer(lambda: self.lexer), input_processors=[ ConditionalProcessor(AppendAutoSuggestion(), has_focus(self.buffer) & ~is_done), ConditionalProcessor(processor=PasswordProcessor(), filter=to_filter(password)), BeforeInput(prompt, style='class:text-area.prompt'), ] + input_processors, search_buffer_control=search_control, preview_search=preview_search, focusable=focusable, focus_on_click=focus_on_click) if multiline: if scrollbar: right_margins = [ScrollbarMargin(display_arrows=True)] else: right_margins = [] if line_numbers: left_margins = [NumberedMargin()] else: left_margins = [] else: height = D.exact(1) left_margins = [] right_margins = [] style = 'class:text-area ' + style self.window = Window( height=height, width=width, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, content=self.control, style=style, wrap_lines=Condition(lambda: is_true(self.wrap_lines)), left_margins=left_margins, right_margins=right_margins, get_line_prefix=get_line_prefix)
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 = _completer or FuzzyCompleter( PythonCompleter( self.get_globals, self.get_locals, lambda: self.enable_dictionary_completion, ), enable_fuzzy=Condition(lambda: self.enable_fuzzy_completion), ) 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.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.) # 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 __init__(self, multiline: FilterOrBool = True, password: FilterOrBool = False, focusable: FilterOrBool = True, focus_on_click: FilterOrBool = False, width: AnyDimension = None, height: AnyDimension = None, dont_extend_height: FilterOrBool = False, dont_extend_width: FilterOrBool = False, line_numbers: bool = False, get_line_prefix: Optional[GetLinePrefixCallable] = None, scrollbar: bool = False, style: str = "", search_field: Optional[SearchToolbar] = None, preview_search: FilterOrBool = True, prompt: AnyFormattedText = "", input_processors: Optional[List[Processor]] = None, key_bindings: KeyBindings = None, **kwargs) -> None: super().__init__(multiline=multiline, password=password, focusable=focusable, focus_on_click=focus_on_click, width=width, height=height, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, line_numbers=line_numbers, get_line_prefix=get_line_prefix, scrollbar=scrollbar, style=style, search_field=search_field, preview_search=preview_search, prompt=prompt, input_processors=input_processors, **kwargs) if search_field is None: search_control = None elif isinstance(search_field, SearchToolbar): search_control = search_field.control if input_processors is None: input_processors = [] self.control = BufferControl( buffer=self.buffer, lexer=DynamicLexer(lambda: self.lexer), input_processors=[ ConditionalProcessor( AppendAutoSuggestion(), has_focus(self.buffer) & ~is_done ), ConditionalProcessor( processor=PasswordProcessor(), filter=to_filter(password) ), BeforeInput(prompt, style="class:text-area.prompt"), ] + input_processors, search_buffer_control=search_control, preview_search=preview_search, focusable=focusable, focus_on_click=focus_on_click, key_bindings=key_bindings ) if multiline: right_margins = [ScrollbarMargin(display_arrows=True)] \ if scrollbar else [] left_margins = [NumberedMargin()] if line_numbers else [] else: height = D.exact(1) left_margins = [] right_margins = [] style = "class:text-area " + style self.window = Window( height=height, width=width, dont_extend_height=dont_extend_height, dont_extend_width=dont_extend_width, content=self.control, style=style, wrap_lines=Condition(lambda: is_true(self.wrap_lines)), left_margins=left_margins, right_margins=right_margins, get_line_prefix=get_line_prefix )
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