def create_lexer(): g = create_ipython_grammar() return GrammarLexer(g, lexers={ 'percent': SimpleLexer('class:pygments.operator'), 'magic': SimpleLexer('class:pygments.keyword'), 'filename': SimpleLexer('class:pygments.name'), 'python': PygmentsLexer(PythonLexer), 'system': PygmentsLexer(BashLexer), })
def create_command_lexer(): """ Lexer for highlighting of the command line. """ return GrammarLexer(COMMAND_GRAMMAR, lexers={ 'command': SimpleLexer('class:commandline.command'), 'location': SimpleLexer('class:commandline.location'), 'shell_command': PygmentsLexer(BashLexer), })
def create_lexer(): g = create_ipython_grammar() return GrammarLexer( g, lexers={ "percent": SimpleLexer("class:pygments.operator"), "magic": SimpleLexer("class:pygments.keyword"), "filename": SimpleLexer("class:pygments.name"), "python": PygmentsLexer(PythonLexer), "system": PygmentsLexer(BashLexer), }, )
def get_lexer(command_groups, redis_grammar): # pygments token # http://pygments.org/docs/tokens/ lexers_dict = { "key": SimpleLexer("class:key"), "keys": SimpleLexer("class:key"), "index": SimpleLexer("class:integer"), "password": SimpleLexer("class:password"), } lexers_dict.update( {key: SimpleLexer("class:pygments.keyword") for key in command_groups}) lexer = GrammarLexer(redis_grammar, lexers=lexers_dict) return lexer
def __init__( self, prompt: AnyFormattedText = "Shell command: ", enable_global_bindings: FilterOrBool = True, ) -> None: self.prompt = prompt self.enable_global_bindings = to_filter(enable_global_bindings) self.system_buffer = Buffer(name=SYSTEM_BUFFER) self._bindings = self._build_key_bindings() self.buffer_control = BufferControl( buffer=self.system_buffer, lexer=SimpleLexer(style="class:system-toolbar.text"), input_processors=[ BeforeInput(lambda: self.prompt, style="class:system-toolbar") ], key_bindings=self._bindings, ) self.window = Window( self.buffer_control, height=1, style="class:system-toolbar" ) self.container = ConditionalContainer( content=self.window, filter=has_focus(self.system_buffer) )
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 question(message, **kwargs): default = kwargs.pop('default', '') validate_prompt = kwargs.pop('validate', None) if validate_prompt: if inspect.isclass(validate_prompt) and issubclass( validate_prompt, Validator): kwargs['validator'] = validate_prompt() elif callable(validate_prompt): class _InputValidator(Validator): def validate(self, document): verdict = validate_prompt(document.text) if not verdict == True: if verdict == False: verdict = 'invalid input' raise ValidationError(message=verdict, cursor_position=len( document.text)) kwargs['validator'] = _InputValidator() # TODO style defaults on detail level kwargs['style'] = kwargs.pop('style', default_style) qmark = kwargs.pop('qmark', '?') def _get_prompt_tokens(): return [('class:questionmark', qmark), ('class:question', ' %s ' % message)] return prompt(message=_get_prompt_tokens, lexer=SimpleLexer('class:answer'), default=default, **kwargs)
def lex_document(self, document): """ Call the lexer and return a get_tokens_for_line function. """ location = self.editor_buffer.location if location: return PygmentsLexer.from_filename( location, sync_from_start=False).lex_document(document) return SimpleLexer().lex_document(document)
def _build_layout(self) -> Layout: self._reset() layout = Layout( HSplit([ Window( BufferControl(self._buffer, lexer=SimpleLexer("class:answer")), dont_extend_height=True, get_line_prefix=self._get_prompt, ) ])) return layout
def __init__(self, buffer=None, input_processors=None, include_default_input_processors=True, lexer=None, preview_search=False, focusable=True, search_buffer_control=None, menu_position=None, focus_on_click=False, key_bindings=None): from prompt_toolkit.key_binding.key_bindings import KeyBindingsBase assert buffer is None or isinstance(buffer, Buffer) assert input_processors is None or isinstance(input_processors, list) assert isinstance(include_default_input_processors, bool) assert menu_position is None or callable(menu_position) assert lexer is None or isinstance(lexer, Lexer) assert (search_buffer_control is None or callable(search_buffer_control) or isinstance(search_buffer_control, SearchBufferControl)) assert key_bindings is None or isinstance(key_bindings, KeyBindingsBase) self.input_processors = input_processors self.include_default_input_processors = include_default_input_processors self.default_input_processors = [ HighlightSearchProcessor(), HighlightIncrementalSearchProcessor(), HighlightSelectionProcessor(), DisplayMultipleCursors(), ] self.preview_search = to_filter(preview_search) self.focusable = to_filter(focusable) self.focus_on_click = to_filter(focus_on_click) self.buffer = buffer or Buffer() self.menu_position = menu_position self.lexer = lexer or SimpleLexer() self.key_bindings = key_bindings self._search_buffer_control = search_buffer_control #: Cache for the lexer. #: Often, due to cursor movement, undo/redo and window resizing #: operations, it happens that a short time, the same document has to be #: lexed. This is a fairly easy way to cache such an expensive operation. self._fragment_cache = SimpleCache(maxsize=8) self._xy_to_cursor_position = None self._last_click_timestamp = None self._last_get_processed_line = None
def lex_document(self, document): """ Call the lexer and return a get_tokens_for_line function. """ location = self.editor_buffer.location if location: if self.editor_buffer.in_file_explorer_mode: return PygmentsLexer( DirectoryListingLexer, sync_from_start=False).lex_document(document) return PygmentsLexer.from_filename( location, sync_from_start=False).lex_document(document) return SimpleLexer().lex_document(document)
def __init__( self, buffer: Optional[Buffer] = None, input_processors: Optional[List[Processor]] = None, include_default_input_processors: bool = True, lexer: Optional[Lexer] = None, preview_search: FilterOrBool = False, focusable: FilterOrBool = True, search_buffer_control: Union[None, "SearchBufferControl", Callable[[], "SearchBufferControl"]] = None, menu_position: Optional[Callable] = None, focus_on_click: FilterOrBool = False, key_bindings: Optional["KeyBindingsBase"] = None, ): self.input_processors = input_processors self.include_default_input_processors = include_default_input_processors self.default_input_processors = [ HighlightSearchProcessor(), HighlightIncrementalSearchProcessor(), HighlightSelectionProcessor(), DisplayMultipleCursors(), ] self.preview_search = to_filter(preview_search) self.focusable = to_filter(focusable) self.focus_on_click = to_filter(focus_on_click) self.buffer = buffer or Buffer() self.menu_position = menu_position self.lexer = lexer or SimpleLexer() self.key_bindings = key_bindings self._search_buffer_control = search_buffer_control #: Cache for the lexer. #: Often, due to cursor movement, undo/redo and window resizing #: operations, it happens that a short time, the same document has to be #: lexed. This is a fairly easy way to cache such an expensive operation. self._fragment_cache: SimpleCache[Hashable, Callable[ [int], StyleAndTextTuples]] = SimpleCache(maxsize=8) self._last_click_timestamp: Optional[float] = None self._last_get_processed_line: Optional[Callable[ [int], _ProcessedLine]] = None
def get_lexer(command_groups, redis_grammar): """ Input command render color with lexer mapping below """ # pygments token # http://pygments.org/docs/tokens/ lexers_dict = { "key": SimpleLexer("class:key"), "keys": SimpleLexer("class:key"), "value": SimpleLexer("class:string"), "expiration": SimpleLexer("class:integer"), "condition": SimpleLexer("class:const"), "index": SimpleLexer("class:index"), "password": SimpleLexer("class:password"), } lexers_dict.update({key: SimpleLexer("class:command") for key in command_groups}) lexer = GrammarLexer(redis_grammar, lexers=lexers_dict) return lexer
def __init__( self, search_buffer: Optional[Buffer] = None, vi_mode: bool = False, text_if_not_searching: AnyFormattedText = "", forward_search_prompt: AnyFormattedText = "I-search: ", backward_search_prompt: AnyFormattedText = "I-search backward: ", ignore_case: FilterOrBool = False, ) -> None: if search_buffer is None: search_buffer = Buffer() @Condition def is_searching() -> bool: return self.control in get_app().layout.search_links def get_before_input() -> AnyFormattedText: if not is_searching(): return text_if_not_searching elif (self.control.searcher_search_state.direction == SearchDirection.BACKWARD): return "?" if vi_mode else backward_search_prompt else: return "/" if vi_mode else forward_search_prompt self.search_buffer = search_buffer self.control = SearchBufferControl( buffer=search_buffer, input_processors=[ BeforeInput(get_before_input, style="class:search-toolbar.prompt") ], lexer=SimpleLexer(style="class:search-toolbar.text"), ignore_case=ignore_case, ) self.container = ConditionalContainer( content=Window(self.control, height=1, style="class:search-toolbar"), filter=is_searching, )
def loop_prompt(self, start_in_embed=False): """Run prompt loop that keeps reading input line and showing output until exit.""" session: PromptSession[str] = PromptSession( history=self.prompt_history, auto_suggest=AutoSuggestFromHistory(), complete_in_thread=True, enable_history_search=True, lexer=SimpleLexer(), vi_mode=self.use_vi_mode, bottom_toolbar=self.bottom_toolbar, rprompt=self.rprompt, completer=self.completer, ) while True: if start_in_embed: self.cmd.cmd_embed() start_in_embed = False # XXX: is this the only way to change history aside from initiating session in every loop? session.default_buffer.history = self.prompt_history text = session.prompt( "> ", in_thread=True, bottom_toolbar=self.bottom_toolbar, rprompt=self.rprompt, completer=self.completer, ) text = text.replace("\\n", "\n") log.debug(f"got line input: {text!r}") if text.lower().strip() == "exit": return if text.lower().strip() == "help": self.cmd.cmd_help() continue if not text: continue result, meta = self.readline(text) log.debug( f"processed line input to: {result!r} with meta {meta!r}") self.console.print("" if result is None else result) if result: self.output_history.append(result)
def __init__(self, prompt='Shell command: '): self.prompt = prompt self.system_buffer = Buffer(name=SYSTEM_BUFFER) self._global_bindings = self._build_global_key_bindings() self._bindings = self._build_key_bindings() self.buffer_control = BufferControl( buffer=self.system_buffer, lexer=SimpleLexer(style='class:system-toolbar.text'), input_processor=BeforeInput( lambda: self.prompt, style='class:system-toolbar'), key_bindings=self._bindings) self.window = Window( self.buffer_control, height=1, style='class:system-toolbar') self.container = ConditionalContainer( content=self.window, filter=has_focus(self.system_buffer))
def question(message, **kwargs): validate_prompt = kwargs.pop('validate', None) if validate_prompt: if inspect.isclass(validate_prompt) and issubclass(validate_prompt, Validator): kwargs['validator'] = validate_prompt() elif callable(validate_prompt): class _InputValidator(Validator): def validate(self, document): verdict = validate_prompt(document.text) if verdict is True: if verdict is False: verdict = 'invalid input' raise ValidationError( message=verdict, cursor_position=len(document.text)) kwargs['validator'] = _InputValidator() qmark = kwargs.pop('qmark', '?') def _get_prompt_tokens(): return [ ('class:question-mark', qmark), ('class:question', ' %s ' % message) ] session = PromptSession( message=_get_prompt_tokens(), lexer=SimpleLexer(style='class:answer'), style=default_style, **kwargs ) return session.app
def __init__(self, search_buffer=None, vi_mode=False, text_if_not_searching='', forward_search_prompt='I-search: ', backward_search_prompt='I-search backward: ', ignore_case=False): assert search_buffer is None or isinstance(search_buffer, Buffer) if search_buffer is None: search_buffer = Buffer() @Condition def is_searching(): return self.control in get_app().layout.search_links def get_before_input(): if not is_searching(): return text_if_not_searching elif self.control.searcher_search_state.direction == SearchDirection.BACKWARD: return ('?' if vi_mode else backward_search_prompt) else: return ('/' if vi_mode else forward_search_prompt) self.search_buffer = search_buffer self.control = SearchBufferControl( buffer=search_buffer, input_processors=[ BeforeInput(get_before_input, style='class:search-toolbar.prompt') ], lexer=SimpleLexer(style='class:search-toolbar.text'), ignore_case=ignore_case) self.container = ConditionalContainer(content=Window( self.control, height=1, style='class:search-toolbar'), filter=is_searching)
def question(message, **kwargs): default = kwargs.pop('default', '') eargs = kwargs.pop('eargs', {}) validate_prompt = kwargs.pop('validate', None) if validate_prompt: if inspect.isclass(validate_prompt) and issubclass( validate_prompt, Validator): kwargs['validator'] = validate_prompt() elif callable(validate_prompt): class _InputValidator(Validator): def validate(self, document): # print(document) verdict = validate_prompt(document.text) if not verdict == True: if verdict == False: verdict = 'invalid input' raise ValidationError(message=verdict, cursor_position=len( document.text)) kwargs['validator'] = _InputValidator() for k, v in eargs.items(): if v == "" or v == " ": raise EditorArgumentsError( "Args '{}' value should not be empty".format(k)) editor = eargs.get("editor", None) ext = eargs.get("ext", ".txt") env = eargs.get("env", None) text = default filename = eargs.get("filename", None) multiline = True if not editor else False save = eargs.get("save", None) if editor: _text = edit(editor=editor, extension=ext, text=text, env=env, filename=filename, require_save=save) if filename: default = filename else: default = _text # TODO style defaults on detail level kwargs['style'] = kwargs.pop('style', default_style) qmark = kwargs.pop('qmark', '?') def _get_prompt_tokens(): return [('class:questionmark', qmark), ('class:question', ' %s ' % message)] return PromptSession(message=_get_prompt_tokens, lexer=SimpleLexer('class:answer'), multiline=multiline, enable_open_in_editor=True, vi_mode=True, **kwargs)
def autocomplete( message: Text, choices: List[Text], default: Text = "", qmark: Text = DEFAULT_QUESTION_PREFIX, completer: Optional[Completer] = None, meta_information: Optional[Dict[Text, Any]] = None, ignore_case: bool = True, match_middle: bool = True, complete_style: CompleteStyle = CompleteStyle.COLUMN, validate: Any = None, style: Optional[Style] = None, **kwargs: Any, ) -> Question: """Prompt the user to enter a message with autocomplete help. Args: message: Question text choices: Items shown in the selection, this contains items as strings default: Default return value (single value). qmark: Question prefix displayed in front of the question. By default this is a `?` completer: A prompt_toolkit `Completer` implementation. If not set, a questionary completer implementation will be used. meta_information: A dictionary with information/anything about choices. ignore_case: If true autocomplete would ignore case. match_middle: If true autocomplete would search in every string position not only in string begin. complete_style: How autocomplete menu would be shown, it could be COLUMN, MULTI_COLUMN or READLINE_LIKE validate: Require the entered value to pass a validation. The value can not be submitted until the validator accepts it (e.g. to check minimum password length). This can either be a function accepting the input and returning a boolean, or an class reference to a subclass of the prompt toolkit Validator class. style: A custom color and style for the question parts. You can configure colors as well as font types for different elements. Returns: Question: Question instance, ready to be prompted (using `.ask()`). """ merged_style = merge_styles([DEFAULT_STYLE, style]) def get_prompt_tokens() -> List[Tuple[Text, Text]]: return [("class:qmark", qmark), ("class:question", " {} ".format(message))] def get_meta_style( meta: Optional[Dict[Text, Any]]) -> Optional[Dict[Text, Any]]: if meta: for key in meta: meta[key] = HTML("<text>{}</text>").format(meta[key]) return meta validator = build_validator(validate) if completer is None: if not choices: raise ValueError( "No choices is given, you should use Text question.") # use the default completer completer = WordCompleter( choices, ignore_case=ignore_case, meta_information=get_meta_style(meta_information), match_middle=match_middle, ) p = PromptSession( get_prompt_tokens, lexer=SimpleLexer("class:answer"), style=merged_style, completer=completer, validator=validator, complete_style=complete_style, **kwargs, ) p.default_buffer.reset(Document(default)) return Question(p.app)
def create_layout(python_input, lexer=PythonLexer, extra_body=None, extra_toolbars=None, extra_buffer_processors=None, input_buffer_height=None): D = Dimension extra_body = [extra_body] if extra_body else [] extra_toolbars = extra_toolbars or [] extra_buffer_processors = extra_buffer_processors or [] input_buffer_height = input_buffer_height or D(min=6) search_toolbar = SearchToolbar(python_input.search_buffer) def create_python_input_window(): def menu_position(): """ When there is no autocompletion menu to be shown, and we have a signature, set the pop-up position at `bracket_start`. """ b = python_input.default_buffer if b.complete_state is None and python_input.signatures: row, col = python_input.signatures[0].bracket_start index = b.document.translate_row_col_to_index(row - 1, col) return index return Window( BufferControl( buffer=python_input.default_buffer, search_buffer_control=search_toolbar.control, lexer=lexer, include_default_input_processors=False, input_processors=[ ConditionalProcessor( processor=HighlightIncrementalSearchProcessor(), filter=has_focus(SEARCH_BUFFER) | has_focus(search_toolbar.control), ), HighlightSelectionProcessor(), DisplayMultipleCursors(), # Show matching parentheses, but only while editing. ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars='[](){}'), filter=has_focus(DEFAULT_BUFFER) & ~is_done & Condition(lambda: python_input. highlight_matching_parenthesis)), ConditionalProcessor(processor=AppendAutoSuggestion(), filter=~is_done) ] + extra_buffer_processors, menu_position=menu_position, # Make sure that we always see the result of an reverse-i-search: preview_search=True, ), left_margins=[PythonPromptMargin(python_input)], # Scroll offsets. The 1 at the bottom is important to make sure the # cursor is never below the "Press [Meta+Enter]" message which is a float. scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4), # As long as we're editing, prefer a minimal height of 6. height=(lambda: (None if get_app().is_done or python_input. show_exit_confirmation else input_buffer_height)), wrap_lines=Condition(lambda: python_input.wrap_lines), ) root_container = HSplit([ VSplit([ HSplit([ FloatContainer( content=HSplit([create_python_input_window()] + extra_body), floats=[ Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=CompletionsMenu(scroll_offset=( lambda: python_input. completion_menu_scroll_offset), max_height=12), filter=show_completions_menu(python_input))), Float(xcursor=True, ycursor=True, content=ConditionalContainer( content=MultiColumnCompletionsMenu(), filter=show_multi_column_completions_menu( python_input))), Float(xcursor=True, ycursor=True, content=signature_toolbar(python_input)), Float(left=2, bottom=1, content=exit_confirmation(python_input)), Float(bottom=0, right=0, height=1, content=meta_enter_message(python_input), hide_when_covering_content=True), Float(bottom=1, left=1, right=0, content=python_sidebar_help(python_input)), ]), ArgToolbar(), search_toolbar, SystemToolbar(), ValidationToolbar(), ConditionalContainer(content=CompletionsToolbar(), filter=show_completions_toolbar( python_input)), # Docstring region. ConditionalContainer(content=Window( height=D.exact(1), char='\u2500', style='class:separator'), filter=HasSignature(python_input) & ShowDocstring(python_input) & ~is_done), ConditionalContainer( content=Window( BufferControl( buffer=python_input.docstring_buffer, lexer=SimpleLexer(style='class:docstring'), #lexer=PythonLexer, ), height=D(max=12)), filter=HasSignature(python_input) & ShowDocstring(python_input) & ~is_done), ]), ConditionalContainer(content=HSplit([ python_sidebar(python_input), Window(style='class:sidebar,separator', height=1), python_sidebar_navigation(python_input), ]), filter=ShowSidebar(python_input) & ~is_done) ]), ] + extra_toolbars + [ VSplit([ status_bar(python_input), show_sidebar_button_info(python_input), ]) ]) return Layout(root_container)
def __init__(self) -> None: self._current_lexer = self._dummy = SimpleLexer()
def get_lexer(command_groups, redis_grammar): """ Input command render color with lexer mapping below This converts token to styles in style.py """ # pygments token # http://pygments.org/docs/tokens/ lexers_dict = { "key": SimpleLexer("class:key"), "keys": SimpleLexer("class:key"), "newkey": SimpleLexer("class:important-key"), "destination": SimpleLexer("class:important-key"), "member": SimpleLexer("class:member"), "members": SimpleLexer("class:member"), "value": SimpleLexer("class:string"), "values": SimpleLexer("class:string"), "lexmin": SimpleLexer("class:string"), "lexmax": SimpleLexer("class:string"), "bit": SimpleLexer("class:bit"), "expiration": SimpleLexer("class:integer"), "second": SimpleLexer("class:integer"), "millisecond": SimpleLexer("class:integer"), "start": SimpleLexer("class:integer"), "float": SimpleLexer("class:integer"), "end": SimpleLexer("class:integer"), "delta": SimpleLexer("class:integer"), "offset": SimpleLexer("class:integer"), "count": SimpleLexer("class:integer"), "index": SimpleLexer("class:index"), "clientid": SimpleLexer("class:integer"), "password": SimpleLexer("class:password"), "min": SimpleLexer("class:integer"), "max": SimpleLexer("class:integer"), "score": SimpleLexer("class:integer"), "timeout": SimpleLexer("class:integer"), "position": SimpleLexer("class:integer"), "cursor": SimpleLexer("class:integer"), "pattern": SimpleLexer("class:pattern"), "type": SimpleLexer("class:string"), "fields": SimpleLexer("class:field"), "field": SimpleLexer("class:field"), "parameter": SimpleLexer("class:field"), } lexers_dict.update({key: SimpleLexer("class:const") for key in CONST}) lexers_dict.update({key: SimpleLexer("class:command") for key in command_groups}) lexer = GrammarLexer(redis_grammar, lexers=lexers_dict) return lexer
def text( message: Text, default: Text = "", validate: Any = None, qmark: Text = DEFAULT_QUESTION_PREFIX, style: Optional[Style] = None, multiline: bool = False, instruction: Optional[Text] = None, **kwargs: Any, ) -> Question: """Prompt the user to enter a free text message. This question type can be used to prompt the user for some text input. Args: message: Question text default: Default value will be returned if the user just hits enter. validate: Require the entered value to pass a validation. The value can not be submited until the validator accepts it (e.g. to check minimum password length). This can either be a function accepting the input and returning a boolean, or an class reference to a subclass of the prompt toolkit Validator class. qmark: Question prefix displayed in front of the question. By default this is a `?` style: A custom color and style for the question parts. You can configure colors as well as font types for different elements. multiline: If `True`, multiline input will be enabled. instruction: Write instructions for the user if needed. If `None` and `multiline=True`, some instructions will appear. Returns: Question: Question instance, ready to be prompted (using `.ask()`). """ merged_style = merge_styles([DEFAULT_STYLE, style]) validator = build_validator(validate) if instruction is None and multiline: instruction = INSTRUCTION_MULTILINE def get_prompt_tokens() -> List[Tuple[Text, Text]]: result = [("class:qmark", qmark), ("class:question", " {} ".format(message))] if instruction: result.append(("class:instruction", " {} ".format(instruction))) return result p = PromptSession( get_prompt_tokens, style=merged_style, validator=validator, lexer=SimpleLexer("class:answer"), multiline=multiline, **kwargs, ) p.default_buffer.reset(Document(default)) return Question(p.app)
def get_lexer_mapping(): """ Input command render color with lexer mapping below This converts token to styles in style.py """ # pygments token # http://pygments.org/docs/tokens/ lexers_dict = { "key": SimpleLexer("class:key"), "keys": SimpleLexer("class:key"), "newkey": SimpleLexer("class:important-key"), "destination": SimpleLexer("class:important-key"), "member": SimpleLexer("class:member"), "members": SimpleLexer("class:member"), "value": SimpleLexer("class:string"), "svalue": SimpleLexer("class:string"), "values": SimpleLexer("class:string"), "lexmin": SimpleLexer("class:string"), "lexmax": SimpleLexer("class:string"), "bit": SimpleLexer("class:bit"), "expiration": SimpleLexer("class:integer"), "second": SimpleLexer("class:integer"), "millisecond": SimpleLexer("class:integer"), "start": SimpleLexer("class:integer"), "float": SimpleLexer("class:integer"), "end": SimpleLexer("class:integer"), # stream id "stream_id": SimpleLexer("class:integer"), "group": SimpleLexer("class:group"), "delta": SimpleLexer("class:integer"), "offset": SimpleLexer("class:integer"), "count": SimpleLexer("class:integer"), "index": SimpleLexer("class:index"), "clientid": SimpleLexer("class:integer"), "password": SimpleLexer("class:password"), "min": SimpleLexer("class:integer"), "max": SimpleLexer("class:integer"), "score": SimpleLexer("class:integer"), "timeout": SimpleLexer("class:integer"), "position": SimpleLexer("class:integer"), "cursor": SimpleLexer("class:integer"), "pattern": SimpleLexer("class:pattern"), "type": SimpleLexer("class:string"), "fields": SimpleLexer("class:field"), "field": SimpleLexer("class:field"), "sfield": SimpleLexer("class:field"), "parameter": SimpleLexer("class:field"), "channel": SimpleLexer("class:channel"), "double_lua": PygmentsLexer(LuaLexer), "single_lua": PygmentsLexer(LuaLexer), "command": SimpleLexer("class:command"), "approximately": SimpleLexer("class:const"), } lexers_dict.update({key: SimpleLexer("class:const") for key in CONST}) return lexers_dict
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 autocomplete( message: str, choices: List[str], default: str = "", qmark: str = DEFAULT_QUESTION_PREFIX, completer: Optional[Completer] = None, meta_information: Optional[Dict[str, Any]] = None, ignore_case: bool = True, match_middle: bool = True, complete_style: CompleteStyle = CompleteStyle.COLUMN, validate: Any = None, style: Optional[Style] = None, **kwargs: Any, ) -> Question: """Prompt the user to enter a message with autocomplete help. Example: >>> import questionary >>> questionary.autocomplete( ... 'Choose ant specie', ... choices=[ ... 'Camponotus pennsylvanicus', ... 'Linepithema humile', ... 'Eciton burchellii', ... "Atta colombica", ... 'Polyergus lucidus', ... 'Polyergus rufescens', ... ]).ask() ? Choose ant specie Atta colombica 'Atta colombica' .. image:: ../images/autocomplete.gif This is just a realy basic example, the prompt can be customised using the parameters. Args: message: Question text choices: Items shown in the selection, this contains items as strings default: Default return value (single value). qmark: Question prefix displayed in front of the question. By default this is a ``?`` completer: A prompt_toolkit :class:`prompt_toolkit.completion.Completion` implementation. If not set, a questionary completer implementation will be used. meta_information: A dictionary with information/anything about choices. ignore_case: If true autocomplete would ignore case. match_middle: If true autocomplete would search in every string position not only in string begin. complete_style: How autocomplete menu would be shown, it could be ``COLUMN`` ``MULTI_COLUMN`` or ``READLINE_LIKE`` from :class:`prompt_toolkit.shortcuts.CompleteStyle`. validate: Require the entered value to pass a validation. The value can not be submitted until the validator accepts it (e.g. to check minimum password length). This can either be a function accepting the input and returning a boolean, or an class reference to a subclass of the prompt toolkit Validator class. style: A custom color and style for the question parts. You can configure colors as well as font types for different elements. Returns: :class:`Question`: Question instance, ready to be prompted (using ``.ask()``). """ merged_style = merge_styles([DEFAULT_STYLE, style]) def get_prompt_tokens() -> List[Tuple[str, str]]: return [("class:qmark", qmark), ("class:question", " {} ".format(message))] def get_meta_style(meta: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: if meta: for key in meta: meta[key] = HTML("<text>{}</text>").format(meta[key]) return meta validator = build_validator(validate) if completer is None: if not choices: raise ValueError("No choices is given, you should use Text question.") # use the default completer completer = WordCompleter( choices, ignore_case=ignore_case, meta_information=get_meta_style(meta_information), match_middle=match_middle, ) p = PromptSession( get_prompt_tokens, lexer=SimpleLexer("class:answer"), style=merged_style, completer=completer, validator=validator, complete_style=complete_style, **kwargs, ) p.default_buffer.reset(Document(default)) return Question(p.app)
return compile(r""" (\s* (?P<operator>[a-z]+) (\s+ (?P<var>[0-9.]+) )*) """) example_style = Style.from_dict({ 'filter': '#33aa33 bold', 'trailing-input': 'bg:#662222 #ffffff', }) if __name__ == '__main__': g = create_grammar() lexer = GrammarLexer(g, lexers={ 'operator': SimpleLexer('class:operator'), 'var': SimpleLexer('class:number'), }) completer = GrammarCompleter(g, { 'operator': WordCompleter(operators), }) try: # REPL loop. while True: # Read input and parse the result. text = prompt('Calculate: ', lexer=lexer, completer=completer, style=example_style)
def path( message: str, default: str = "", qmark: str = DEFAULT_QUESTION_PREFIX, validate: Any = None, style: Optional[Style] = None, only_directories: bool = False, file_filter: Optional[Callable[[str], bool]] = None, complete_style: CompleteStyle = CompleteStyle.MULTI_COLUMN, **kwargs: Any, ) -> Question: """A text input for a file or directory path with autocompletion enabled. Example: >>> import questionary >>> questionary.path("What's the path to the projects version file?").ask() ? What's the path to the projects version file? ./pyproject.toml './pyproject.toml' .. image:: ../images/path.gif This is just a really basic example, the prompt can be customised using the parameters. Args: message: Question text. default: Default return value (single value). qmark: Question prefix displayed in front of the question. By default this is a ``?``. complete_style: How autocomplete menu would be shown, it could be ``COLUMN`` ``MULTI_COLUMN`` or ``READLINE_LIKE`` from :class:`prompt_toolkit.shortcuts.CompleteStyle`. validate: Require the entered value to pass a validation. The value can not be submitted until the validator accepts it (e.g. to check minimum password length). This can either be a function accepting the input and returning a boolean, or an class reference to a subclass of the prompt toolkit Validator class. style: A custom color and style for the question parts. You can configure colors as well as font types for different elements. only_directories: Only show directories in auto completion file_filter: Optional callable to filter suggested paths. Only paths where the passed callable evaluates to ``True`` will show up in the suggested paths. This does not validate the typed path, e.g. it is still possible for the user to enter a path manually, even though this filter evaluates to ``False``. If in addition to filtering suggestions you also want to validate the result, use ``validate`` in combination with the ``file_filter``. Returns: :class:`Question`: Question instance, ready to be prompted (using ``.ask()``). """ merged_style = merge_styles([DEFAULT_STYLE, style]) def get_prompt_tokens() -> List[Tuple[str, str]]: return [("class:qmark", qmark), ("class:question", " {} ".format(message))] validator = build_validator(validate) bindings = KeyBindings() @bindings.add(Keys.ControlM, eager=True) def set_answer(event: KeyPressEvent): if event.current_buffer.complete_state is not None: event.current_buffer.complete_state = None elif event.app.current_buffer.validate(set_cursor=True): # When the validation succeeded, accept the input. result_path = event.app.current_buffer.document.text if result_path.endswith(os.path.sep): result_path = result_path[:-1] event.app.exit(result=result_path) event.app.current_buffer.append_to_history() @bindings.add(os.path.sep, eager=True) def next_segment(event: KeyPressEvent): b = event.app.current_buffer if b.complete_state: b.complete_state = None current_path = b.document.text if not current_path.endswith(os.path.sep): b.insert_text(os.path.sep) b.start_completion(select_first=False) p = PromptSession( get_prompt_tokens, lexer=SimpleLexer("class:answer"), style=merged_style, completer=GreatUXPathCompleter(only_directories=only_directories, file_filter=file_filter, expanduser=True), validator=validator, complete_style=complete_style, key_bindings=bindings, **kwargs, ) p.default_buffer.reset(Document(default)) return Question(p.app)
(\s* (?P<operator1>[a-z]+) \s+ (?P<var1>[0-9.]+) \s+ (?P<var2>[0-9.]+) \s*) | (\s* (?P<operator2>[a-z]+) \s+ (?P<var1>[0-9.]+) \s*) """) example_style = Style.from_dict({ 'operator': '#33aa33 bold', 'number': '#ff0000 bold', 'trailing-input': 'bg:#662222 #ffffff', }) g = create_grammar() lexer = GrammarLexer(g, lexers={ 'operator1': SimpleLexer('class:operator'), 'operator2': SimpleLexer('class:operator'), 'var1': SimpleLexer('class:number'), 'var2': SimpleLexer('class:number'), }) completer = GrammarCompleter( g, { 'operator1': WordCompleter(operators1), 'operator2': WordCompleter(operators2), }) #TODO : this should probably be a functor/lens (two way communication, see ML applications...) def dummy_inner_loop(inner_in): """A dummy pure function as scaffold"""