def _get_positions_to_highlight(self, document):
        """
        Return a list of (row, col) tuples that need to be highlighted.
        """
        # Try for the character under the cursor.
        if document.current_char and document.current_char in self.chars:
            pos = document.find_matching_bracket_position(
                    start_pos=document.cursor_position - self.max_cursor_distance,
                    end_pos=document.cursor_position + self.max_cursor_distance)

        # Try for the character before the cursor.
        elif (document.char_before_cursor and document.char_before_cursor in
              self._closing_braces and document.char_before_cursor in self.chars):
            document = Document(document.text, document.cursor_position - 1)

            pos = document.find_matching_bracket_position(
                    start_pos=document.cursor_position - self.max_cursor_distance,
                    end_pos=document.cursor_position + self.max_cursor_distance)
        else:
            pos = None

        # Return a list of (row, col) tuples that need to be highlighted.
        if pos:
            pos += document.cursor_position  # pos is relative.
            row, col = document.translate_index_to_position(pos)
            return [(row, col), (document.cursor_position_row, document.cursor_position_col)]
        else:
            return []
Esempio n. 2
0
    def create_copy_document(self):
        """
        Create a Document instance and token list that can be used in copy
        mode.
        """
        data_buffer = self.screen.pt_screen.data_buffer
        text = []
        token_list = []

        first_row = min(data_buffer.keys())
        last_row = max(data_buffer.keys())

        def token_has_no_background(token):
            try:
                # Token looks like ('C', color, bgcolor, bold, underline, ...)
                return token[2] is None
            except IndexError:
                return True

        for row_index in range(first_row, last_row + 1):
            row = data_buffer[row_index]
            max_column = max(row.keys()) if row else 0

            # Remove trailing whitespace. (If the background is transparent.)
            row_data = [row[x] for x in range(0, max_column + 1)]

            while (row_data and row_data[-1].char.isspace() and
                   token_has_no_background(row_data[-1].token)):
                row_data.pop()

            # Walk through row.
            char_iter = iter(range(len(row_data)))

            for x in char_iter:
                c = row[x]
                text.append(c.char)
                token_list.append((c.token, c.char))

                # Skip next cell when this is a double width character.
                if c.width == 2:
                    next(char_iter)

            # Add newline.
            text.append('\n')
            token_list.append((Token, '\n'))

        # Remove newlines at the end.
        while text and text[-1] == '\n':
            text.pop()
            token_list.pop()

        # Calculate cursor position.
        d = Document(text=''.join(text))

        return Document(text=d.text,
                        cursor_position=d.translate_row_col_to_index(
                            row=self.screen.pt_screen.cursor_position.y,
                            col=self.screen.pt_screen.cursor_position.x)), token_list
Esempio n. 3
0
class DocumentTest(unittest.TestCase):
    def setUp(self):
        self.document = Document(
            'line 1\n' +
            'line 2\n' +
            'line 3\n' +
            'line 4\n',
            len('line 1\n' + 'lin')
        )

    def test_current_char(self):
        self.assertEqual(self.document.current_char, 'e')

    def test_text_before_cursor(self):
        self.assertEqual(self.document.text_before_cursor, 'line 1\nlin')

    def test_text_after_cursor(self):
        self.assertEqual(self.document.text_after_cursor,
                         'e 2\n' +
                         'line 3\n' +
                         'line 4\n')

    def test_lines(self):
        self.assertEqual(self.document.lines, [
                         'line 1',
                         'line 2',
                         'line 3',
                         'line 4', ''])

    def test_line_count(self):
        self.assertEqual(self.document.line_count, 5)

    def test_current_line_before_cursor(self):
        self.assertEqual(self.document.current_line_before_cursor, 'lin')

    def test_current_line_after_cursor(self):
        self.assertEqual(self.document.current_line_after_cursor, 'e 2')

    def test_current_line(self):
        self.assertEqual(self.document.current_line, 'line 2')

    def test_cursor_position(self):
        self.assertEqual(self.document.cursor_position_row, 1)
        self.assertEqual(self.document.cursor_position_col, 3)

        d = Document('', 0)
        self.assertEqual(d.cursor_position_row, 0)
        self.assertEqual(d.cursor_position_col, 0)

    def test_translate_index_to_position(self):
        pos = self.document.translate_index_to_position(
            len('line 1\nline 2\nlin'))

        self.assertEqual(pos[0], 2)
        self.assertEqual(pos[1], 3)

        pos = self.document.translate_index_to_position(0)
        self.assertEqual(pos, (0, 0))
Esempio n. 4
0
    def _get_source_code_document(self, filename):
        """
        Return source code around current line as string.
        """
        source_code = ''.join(linecache.getlines(filename))
        document = Document(source_code)

        return Document(document.text, document.translate_row_col_to_index(
            row=self.curframe.f_lineno - 1, col=0))
Esempio n. 5
0
 def setUp(self):
     self.document = Document(
         'line 1\n' +
         'line 2\n' +
         'line 3\n' +
         'line 4\n',
         len('line 1\n' + 'lin')
     )
    def __init__(self, python_input, original_document):
        """
        Create an `Application` for the history screen.
        This has to be run as a sub application of `python_input`.

        When this application runs and returns, it retuns the selected lines.
        """
        self.python_input = python_input

        history_mapping = HistoryMapping(self, python_input.history, original_document)
        self.history_mapping = history_mapping

        document = Document(history_mapping.concatenated_history)
        document = Document(
            document.text,
            cursor_position=document.cursor_position + document.get_start_of_line_position())

        self.history_buffer = Buffer(
            document=document,
            on_cursor_position_changed=self._history_buffer_pos_changed,
            accept_handler=(
                lambda buff: get_app().exit(result=self.default_buffer.text)),
            read_only=True)

        self.default_buffer = Buffer(
            name=DEFAULT_BUFFER,
            document=history_mapping.get_new_document(),
            on_cursor_position_changed=self._default_buffer_pos_changed,
            read_only=True)

        self.help_buffer = Buffer(
            document=Document(HELP_TEXT, 0),
            read_only=True
        )

        self.history_layout = HistoryLayout(self)

        self.app = Application(
            layout=self.history_layout.layout,
            full_screen=True,
            style=python_input._current_style,
            mouse_support=Condition(lambda: python_input.enable_mouse_support),
            key_bindings=create_key_bindings(self, python_input, history_mapping)
        )
    def _get_fuzzy_completions(
            self, document: Document, complete_event: CompleteEvent) -> Iterable[Completion]:

        word_before_cursor = document.get_word_before_cursor(
            pattern=re.compile(self._get_pattern()))

        # Get completions
        document2 = Document(
            text=document.text[:document.cursor_position - len(word_before_cursor)],
            cursor_position=document.cursor_position - len(word_before_cursor))

        completions = list(self.completer.get_completions(document2, complete_event))

        fuzzy_matches: List[_FuzzyMatch] = []

        pat = '.*?'.join(map(re.escape, word_before_cursor))
        pat = '(?=({0}))'.format(pat)   # lookahead regex to manage overlapping matches
        regex = re.compile(pat, re.IGNORECASE)
        for compl in completions:
            matches = list(regex.finditer(compl.text))
            if matches:
                # Prefer the match, closest to the left, then shortest.
                best = min(matches, key=lambda m: (m.start(), len(m.group(1))))
                fuzzy_matches.append(_FuzzyMatch(len(best.group(1)), best.start(), compl))

        def sort_key(fuzzy_match: '_FuzzyMatch') -> Tuple[int, int]:
            " Sort by start position, then by the length of the match. "
            return fuzzy_match.start_pos, fuzzy_match.match_length

        fuzzy_matches = sorted(fuzzy_matches, key=sort_key)

        for match in fuzzy_matches:
            # Include these completions, but set the correct `display`
            # attribute and `start_position`.
            yield Completion(
                match.completion.text,
                start_position=match.completion.start_position - len(word_before_cursor),
                display_meta=match.completion.display_meta,
                display=self._get_display(match, word_before_cursor),
                style=match.completion.style)
Esempio n. 8
0
    def get_completions(self,
                        document: Document,
                        _complete_event: CompleteEvent = None) -> Sequence[Completion]:
        """
        Returns a sequence of completions for given command line.
        """
        incomplete_cmd = ''
        if document.text.strip():
            incomplete_cmd = document.text.strip().split(maxsplit=1)[0]

        start, end = document.find_boundaries_of_current_word(WORD=True)
        start += document.cursor_position
        end += document.cursor_position
        current_word = document.text[start:end]

        current_word_is_command = (document.text[:start].strip() == '')
        if current_word_is_command:
            return self._complete_commands(incomplete_cmd)

        try:
            cmd = self._cmds.choose(incomplete_cmd)
        except ValueError:
            # invalid command
            return []

        incomplete_param = current_word
        if '=' not in incomplete_param:
            return self._complete_params(cmd, incomplete_param)

        param_name, incomplete_value = incomplete_param.split('=', maxsplit=1)
        param = cmd.parameters.get(param_name)
        if not param:
            return []

        # TODO: would be cool to exclude existing params
        return self._complete_value(param.type, incomplete_value)
Esempio n. 9
0
 def test_substring_completion(self):
     self.init4()
     doc = Document(u'create')
     gen = self.completer.get_completions(doc, None)
     self.assertEqual(six.next(gen), Completion(
         "createmore", -6))
Esempio n. 10
0
 def get_path_matches(self, _, word_before_cursor):
     completer = PathCompleter(expanduser=True)
     document = Document(text=word_before_cursor,
                         cursor_position=len(word_before_cursor))
     for c in completer.get_completions(document, None):
         yield Match(completion=c, priority=None)
Esempio n. 11
0
def test_builtin_function_name_completion(completer, complete_event):
    text = 'SELECT MA'
    position = len('SELECT MA')
    result = completer.get_completions(
        Document(text=text, cursor_position=position), complete_event)
    assert set(result) == set([Completion(text='MAX', start_position=-2)])
Esempio n. 12
0
 def text(self, value):
     self.buffer.set_document(Document(value, 0), bypass_readonly=True)
Esempio n. 13
0
    def assertPromptValidate(self, prompt_mock, value):
        validator = prompt_mock.call_args[1]['validator']

        validator.validate(Document(text=six.text_type(value)))
Esempio n. 14
0
 def __send_to_output(self, message):
     new_text = self.output_buffer.text + "{}\n".format(message)
     self.output_buffer.document = Document(text=new_text,
                                            cursor_position=len(new_text))
Esempio n. 15
0
 def validate(self, document):
     document = Document(text=self.isp.transform_cell(document.text))
     super(IPythonValidator, self).validate(document)
Esempio n. 16
0
def sync_cursor(source_buffer, target_buffer):
    old_target_text = target_buffer.document.text
    source_row = source_buffer.document.cursor_position_row
    target_buffer.set_document(Document(old_target_text, 0), True)
    if source_row > 0:
        target_buffer.cursor_down(count=source_row)
Esempio n. 17
0
 def set_prompt(self, prompt_command="", position=0):
     """ writes the prompt line """
     self.description_docs = u'{}'.format(prompt_command)
     self.cli.current_buffer.reset(initial_document=Document(
         self.description_docs, cursor_position=position))
     self.cli.request_redraw()
Esempio n. 18
0
            fragments += ti.fragments[1:]
        else:
            fragments = ti.fragments

        source_to_display = lambda i: i
        display_to_source = lambda i: i

        return Transformation(fragments,
                              source_to_display=source_to_display,
                              display_to_source=display_to_source)

    def __repr__(self) -> str:
        return 'AddStyleToDiff(%r, %r)' % (self.text, self.style)


local_file_buffer = Buffer(document=Document("".join(a), 0),
                           read_only=True)  # Editable buffer.
local_file_buffer_control = BufferControl(buffer=local_file_buffer,
                                          input_processors=[
                                              AddStyleToDiff("bg:#222222")
                                          ])  # Editable buffer.

remote_file_buffer = Buffer(document=Document("".join(b), 0),
                            read_only=True)  # Editable buffer.


def sync_cursor(source_buffer, target_buffer):
    old_target_text = target_buffer.document.text
    source_row = source_buffer.document.cursor_position_row
    target_buffer.set_document(Document(old_target_text, 0), True)
    if source_row > 0:
Esempio n. 19
0
 def msg_out(self, text: str) -> None:
     new_text = self.msg_field.text + f'\n{text}'
     self.msg_field.buffer.document = \
         Document(text=new_text, cursor_position=len(new_text))
Esempio n. 20
0
 def update_status(self):
     self.status_field.buffer.document = Document(text=self.status)
 def text(self, value: str) -> None:
     self.document = Document(value, 0)
Esempio n. 22
0
    def source(self, event):
        """
        Show and modify source of the object under cursor.
        """

        source_is_already_open = False
        for tab in self.session.tabs:
            if tab.name == 'Source':
                source_is_already_open = True

        if not source_is_already_open:
            cursor_row_index = self.python_code_buffer.document.cursor_position_row
            cursor_col_index = self.python_code_buffer.document.cursor_position_col
            current_row = self.python_code_buffer.document.lines[
                cursor_row_index]
            text_before_cursor = current_row[:cursor_col_index]

            self.inspected_class_object, self.inspected_method_object, source_code = inspect_code(
                text_before_cursor, self.interface)

            self.source_code_original = source_code
            self.source_code_buffer = Buffer()
            self.source_code_buffer.document = Document(text=source_code)

            formatted_text = BufferControl(buffer=self.source_code_buffer,
                                           lexer=PythonLexer(
                                               self.source_code_buffer))

            source_window = Window(formatted_text, width=120, wrap_lines=True)

            tab_index = self.session.add_tab(Tab("Source", source_window))
            self.tabs_container.set_selected_tab(tab_index)

        # Source float is already exist, so saving the modified version of the source and closing the float.
        else:
            # Source code modifications only works on method right now.
            # so it only works if source code inspector return both class ans method object.
            if self.inspected_class_object and \
               self.inspected_method_object and \
               self.source_code_original != self.source_code_buffer.document.text: # Only modify the method object if the code has actually changed
                try:
                    # Should be method definition
                    source = self.source_code_buffer.document.text

                    # Evaluting the method object (with the original name)
                    exec(source, self.interface)

                    method_name = self.inspected_method_object.__name__

                    # The moment we evaluated the new method in the exec above,
                    # we can get a pointer to that method using its name in the local context(scope)
                    new_method_object = eval(method_name, self.interface)

                    setattr(
                        self.inspected_class_object, method_name,
                        new_method_object.__get__(
                            self.inspected_class_object,
                            type(self.inspected_class_object)))

                    # setattr(class_object, method_name, eval(method_name))
                except Exception as e:
                    self.__send_to_output("Exception: {}".format(e))

            self.session.remove_tab_by_name("Source")
            self.tabs_container.update_selected_tab()
def test_special_name_completion(completer, complete_event):
    text = '\\d'
    position = len('\\d')
    result = completer.get_completions(
        Document(text=text, cursor_position=position), complete_event)
    assert result == [Completion(text='\\dt', start_position=-2)]
Esempio n. 24
0
def test_non_empty_text_validator_with_valid_input(user_input):
    validator = io_utils.not_empty_validator("error message")

    document = Document(user_input)
    # If there is input there shouldn't be an exception
    assert validator.validate(document) is None
Esempio n. 25
0
    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):
        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.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)
Esempio n. 26
0
        def search_once(working_index, document):
            """
            Do search one time.
            Return (working_index, document) or `None`
            """
            if direction == SearchDirection.FORWARD:
                # Try find at the current input.
                new_index = document.find(
                    text,
                    include_current_position=include_current_position,
                    ignore_case=ignore_case)

                if new_index is not None:
                    return (working_index,
                            Document(document.text,
                                     document.cursor_position + new_index))
                else:
                    # No match, go forward in the history. (Include len+1 to wrap around.)
                    # (Here we should always include all cursor positions, because
                    # it's a different line.)
                    for i in range(working_index + 1,
                                   len(self._working_lines) + 1):
                        i %= len(self._working_lines)

                        # modified by rtichoke
                        if not no_duplicates or self._working_lines[
                                i] not in self.search_history:
                            document = Document(self._working_lines[i], 0)
                            new_index = document.find(
                                text,
                                include_current_position=True,
                                ignore_case=ignore_case)
                            if new_index is not None:
                                return (i, Document(document.text, new_index))
            else:
                # Try find at the current input.
                new_index = document.find_backwards(text,
                                                    ignore_case=ignore_case)

                if new_index is not None:
                    return (working_index,
                            Document(document.text,
                                     document.cursor_position + new_index))
                else:
                    # No match, go back in the history. (Include -1 to wrap around.)
                    for i in range(working_index - 1, -2, -1):
                        i %= len(self._working_lines)

                        # modified by rtichoke
                        if not no_duplicates or self._working_lines[
                                i] not in self.search_history:
                            document = Document(self._working_lines[i],
                                                len(self._working_lines[i]))
                            new_index = document.find_backwards(
                                text, ignore_case=ignore_case)
                            if new_index is not None:
                                return (i,
                                        Document(
                                            document.text,
                                            len(document.text) + new_index))
Esempio n. 27
0
def document():
    return Document('line 1\n' + 'line 2\n' + 'line 3\n' + 'line 4\n',
                    len('line 1\n' + 'lin'))
Esempio n. 28
0
 def get_completions(self, text, cursor_positition):
     with self._completer_lock:
         return self.completer.get_completions(
             Document(text=text, cursor_position=cursor_positition), None)
Esempio n. 29
0
 def get_completions(self, document : Document, complete_event : CompleteEvent) -> Completion:
     for cmd, color in zip((MyCompleter.CMD + MyCompleter.OTHER), (('bg:ansiblack fg:ansired',) * len(MyCompleter.CMD)) + (('bg:ansiyellow fg:ansiblack',) * len(MyCompleter.OTHER))):
         last_word = document.get_word_under_cursor()
         if cmd.startswith(last_word) and not last_word == '':
             yield Completion(cmd, start_position=-len(last_word), style=color)
Esempio n. 30
0
 def info(self, string):
     """Output given string as info, which is a right justified text element."""
     width = click.get_terminal_size()[0]
     output = string.rjust(width)
     output = self.output.text + '\n' + output
     self.output.document = Document(text=output, cursor_position=len(output))
Esempio n. 31
0
def test_select_keyword_completion(completer, complete_event):
    text = 'SEL'
    position = len('SEL')
    result = completer.get_completions(
        Document(text=text, cursor_position=position), complete_event)
    assert set(result) == set([Completion(text='SELECT', start_position=-3)])
Esempio n. 32
0
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 really 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)
Esempio n. 33
0
    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,
        validator: Optional[Validator] = None,
        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.validator = validator

        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)),
            validator=DynamicValidator(lambda: self.validator),
            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,
        )
Esempio n. 34
0
def _print(field, st):
    s = field.text + st.replace('\r', '')
    field.buffer.document = Document(text=s, cursor_position=len(s))
Esempio n. 35
0
    def find_completions(self, document: Document) -> dict:
        """
            Find tab completions from the commands repository.

            Completions are returned based on tokens extracted
            from the command text received by prompt_toolkit. A
            dictionary is then walked, matching a token to a
            nested dictionary until no more dictionaries are
            available. The resultant dictionary then becomes
            the suggestions for tab completion.

            Some commands may have 'dynamic' completions, such as
            file system related commands. They are defined with a
            'dynamic' key, and the method defined as the value for
            this key is executed to get completions.

            :param document:
            :return:
        """

        # extract tokens from the document similar to
        # how a shell invocation would have been done
        tokens = get_tokens(document.text)

        # start with the current suggestions dictionary being
        # all commands
        current_suggestions = self.COMMANDS

        # when the tokens are extracted, we are expecting something in
        # the format of:
        #   command sub_command sub_sub_command
        # so, lets use that and serach the the COMMAND dictionary for
        # the last dictionary with a correct suggestion
        for token in tokens:

            candidate = token.lower()

            if candidate in list(current_suggestions.keys()):

                # if there are sub commands, grab them
                if 'commands' in current_suggestions[candidate]:
                    current_suggestions = current_suggestions[candidate]['commands']

                # dynamic commands change based on the current status of the
                # environment, so, call the method defined
                elif 'dynamic' in current_suggestions[candidate]:
                    current_suggestions = current_suggestions[candidate]['dynamic']()

                # in this case, there are probably no sub commands, so return
                # an empty dictionary
                else:
                    return {}

        suggestions = {}

        # once we have the deepest suggestions dictionary in the
        # current_suggestions variable, loop through and check for
        # 'sorta' matched versions
        if current_suggestions and len(current_suggestions) > 0:
            for k, _ in current_suggestions.items():

                # fuzzy-ish matching when part of a word is in a suggestion
                if document.get_word_before_cursor().lower() in k.lower():
                    suggestions[k] = current_suggestions[k]

        return suggestions
Esempio n. 36
0
 def set_doc():
     self.pt_cli.application.buffer.document = Document(s)
Esempio n. 37
0
 def setUp(self):
     self.document = Document()
Esempio n. 38
0
    def _run(self):
        class MenuColorizer(Processor):
            def apply_transformation(_self, ti):
                return self._transform_line(ti)

        # keybindings
        self._kb = KeyBindings()

        @self._kb.add('q', filter=~is_searching)
        @self._kb.add('c-c')
        def quit(event):
            event.app.exit()

        @self._kb.add('down', filter=~is_searching)
        @self._kb.add('j', filter=~is_searching)
        def down(event):
            self.next_item(1)

        @self._kb.add('up', filter=~is_searching)
        @self._kb.add('k', filter=~is_searching)
        def up(event):
            self.next_item(-1)

        @self._kb.add('N', filter=~is_searching)
        @self._kb.add('n', filter=~is_searching)
        def search_inc(event, filter=is_searching):
            if not self._bufctrl.search_state.text:
                return

            search_dir = 1 if event.data == 'n' else -1
            sr_lines = self._get_search_result_lines()
            if sr_lines:
                line = sr_lines[search_dir] if len(
                    sr_lines) > 1 else sr_lines[0]
                self.sync_cursor_to_line(line, search_dir)

        @self._kb.add('c-m', filter=~is_searching)
        @self._kb.add('right', filter=~is_searching)
        def accept(event):
            self._success = True
            event.app.exit()

        @self._kb.add('c-m', filter=is_searching)
        def accept_search(event):
            search.accept_search()
            new_line, _ = self._doc.translate_index_to_position(
                self._buf.cursor_position)
            self.sync_cursor_to_line(new_line)

        self._register_extra_kb_cbs(self._kb)

        self._searchbar = SearchToolbar(ignore_case=True)

        text = '\n'.join(map(lambda _x: _x.text, self._items))
        self._doc = Document(text, cursor_position=self._pos)
        self._buf = Buffer(read_only=True, document=self._doc)
        self._bufctrl = BufferControl(
            self._buf,
            search_buffer_control=self._searchbar.control,
            preview_search=True,
            input_processors=[MenuColorizer()])
        split = HSplit([
            Window(self._bufctrl, wrap_lines=True, always_hide_cursor=True),
            self._searchbar
        ])

        # set initial pos
        self.sync_cursor_to_line(0)

        app = Application(layout=Layout(split),
                          key_bindings=self._kb,
                          full_screen=False,
                          mouse_support=False)

        app.run()
        self._ran = True