예제 #1
0
 def __init__(self, cached_values, window_ids, error=''):
     self.cached_values = cached_values
     self.window_ids = window_ids
     self.error = error
     self.line_edit = LineEdit()
     last_search = cached_values.get('last_search', '')
     self.line_edit.add_text(last_search)
     self.text_marked = bool(last_search)
     self.mode = cached_values.get('mode', 'text')
     self.update_prompt()
     self.mark()
예제 #2
0
class Password(Handler):

    def __init__(self, cli_opts: AskCLIOptions, prompt: str) -> None:
        self.cli_opts = cli_opts
        self.prompt = prompt
        from kittens.tui.line_edit import LineEdit
        self.line_edit = LineEdit(is_password=True)

    def initialize(self) -> None:
        self.cmd.set_cursor_shape('beam')
        self.draw_screen()

    @Handler.atomic_update
    def draw_screen(self) -> None:
        self.cmd.clear_screen()
        if self.cli_opts.message:
            for line in self.cli_opts.message.splitlines():
                self.print(line)
            self.print()
        self.line_edit.write(self.write, self.prompt)

    def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
        self.line_edit.on_text(text, in_bracketed_paste)
        self.draw_screen()

    def on_key(self, key_event: KeyEventType) -> None:
        if self.line_edit.on_key(key_event):
            self.draw_screen()
            return
        if key_event.matches('enter'):
            self.quit_loop(0)
        if key_event.matches('esc'):
            self.quit_loop(1)

    def on_resize(self, screen_size: ScreenSize) -> None:
        self.screen_size = screen_size
        self.draw_screen()

    def on_interrupt(self) -> None:
        self.quit_loop(1)
    on_eot = on_interrupt

    @property
    def response(self) -> str:
        if self._tui_loop.return_code == 0:
            return self.line_edit.current_input
        return ''
예제 #3
0
class Search(Handler):
    def __init__(self, cached_values, window_ids, error=''):
        self.cached_values = cached_values
        self.window_ids = window_ids
        self.error = error
        self.line_edit = LineEdit()
        last_search = cached_values.get('last_search', '')
        self.line_edit.add_text(last_search)
        self.text_marked = bool(last_search)
        self.mode = cached_values.get('mode', 'text')
        self.update_prompt()
        self.mark()

    def update_prompt(self):
        self.prompt = '~> ' if self.mode == 'regex' else '=> '

    def init_terminal_state(self):
        self.write(set_line_wrapping(False))
        self.write(set_window_title(_('Search')))

    def initialize(self):
        self.init_terminal_state()
        self.draw_screen()

    def draw_screen(self):
        self.write(clear_screen())
        if self.window_ids:
            input_text = self.line_edit.current_input
            if self.text_marked:
                self.line_edit.current_input = styled(input_text, reverse=True)
            self.line_edit.write(self.write, self.prompt)
            self.line_edit.current_input = input_text
        if self.error:
            with cursor(self.write):
                self.print('')
                for l in self.error.split('\n'):
                    self.print(l)

    def refresh(self):
        self.draw_screen()
        self.mark()

    def switch_mode(self):
        if self.mode == 'regex':
            self.mode = 'text'
        else:
            self.mode = 'regex'
        self.cached_values['mode'] = self.mode
        self.update_prompt()

    def on_text(self, text, in_bracketed_paste):
        if self.text_marked:
            self.text_marked = False
            self.line_edit.clear()
        self.line_edit.on_text(text, in_bracketed_paste)
        self.refresh()

    def on_key(self, key_event):
        if self.text_marked and key_event.key not in [
                'TAB', 'LEFT_CONTROL', 'RIGHT_CONTROL', 'LEFT_ALT',
                'RIGHT_ALT', 'LEFT_SHIFT', 'RIGHT_SHIFT', 'LEFT_SUPER',
                'RIGHT_SUPER'
        ]:
            self.text_marked = False
            self.refresh()

        if self.line_edit.on_key(key_event):
            self.refresh()
            return

        if key_event.matches('ctrl+u'):
            self.line_edit.clear()
            self.refresh()
        elif key_event.matches('ctrl+a'):
            self.line_edit.home()
            self.refresh()
        elif key_event.matches('ctrl+e'):
            self.line_edit.end()
            self.refresh()
        elif key_event.matches('ctrl+backspace') or key_event.matches(
                'ctrl+w'):
            before, _ = self.line_edit.split_at_cursor()

            try:
                start, _ = reindex(before, SPACE_PATTERN_END, right=True)
            except ValueError:
                start = -1

            try:
                space = before[:start].rindex(' ')
            except ValueError:
                space = 0
            self.line_edit.backspace(len(before) - space)
            self.refresh()
        elif key_event.matches('ctrl+left') or key_event.matches('ctrl+b'):
            before, _ = self.line_edit.split_at_cursor()
            try:
                start, _ = reindex(before, SPACE_PATTERN_END, right=True)
            except ValueError:
                start = -1

            try:
                space = before[:start].rindex(' ')
            except ValueError:
                space = 0
            self.line_edit.left(len(before) - space)
            self.refresh()
        elif key_event.matches('ctrl+right') or key_event.matches('ctrl+f'):
            _, after = self.line_edit.split_at_cursor()
            try:
                _, end = reindex(after, SPACE_PATTERN_START)
            except ValueError:
                end = 0

            try:
                space = after[end:].index(' ') + 1
            except ValueError:
                space = len(after)
            self.line_edit.right(space)
            self.refresh()
        elif key_event.matches('alt+backspace') or key_event.matches('alt+w'):
            before, _ = self.line_edit.split_at_cursor()

            try:
                start, _ = reindex(before,
                                   NON_ALPHANUM_PATTERN_END,
                                   right=True)
            except ValueError:
                start = -1
            else:
                self.line_edit.backspace(len(before) - start)
                self.refresh()
                return

            try:
                start, _ = reindex(before, NON_ALPHANUM_PATTERN, right=True)
            except ValueError:
                self.line_edit.backspace(len(before))
                self.refresh()
                return

            self.line_edit.backspace(len(before) - (start + 1))
            self.refresh()
        elif key_event.matches('alt+left') or key_event.matches('alt+b'):
            before, _ = self.line_edit.split_at_cursor()

            try:
                start, _ = reindex(before,
                                   NON_ALPHANUM_PATTERN_END,
                                   right=True)
            except ValueError:
                start = -1
            else:
                self.line_edit.left(len(before) - start)
                self.refresh()
                return

            try:
                start, _ = reindex(before, NON_ALPHANUM_PATTERN, right=True)
            except ValueError:
                self.line_edit.left(len(before))
                self.refresh()
                return

            self.line_edit.left(len(before) - (start + 1))
            self.refresh()
        elif key_event.matches('alt+right') or key_event.matches('alt+f'):
            _, after = self.line_edit.split_at_cursor()

            try:
                _, end = reindex(after, NON_ALPHANUM_PATTERN_START)
            except ValueError:
                end = 0
            else:
                self.line_edit.right(end)
                self.refresh()
                return

            try:
                _, end = reindex(after, NON_ALPHANUM_PATTERN)
            except ValueError:
                self.line_edit.right(len(after))
                self.refresh()
                return

            self.line_edit.right(end - 1)
            self.refresh()
        elif key_event.matches('tab'):
            self.switch_mode()
            self.refresh()
        elif key_event.matches('up'):
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'kitten', match_arg,
                     str(SCROLLMARK_FILE)])
        elif key_event.matches('down'):
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'kitten', match_arg,
                     str(SCROLLMARK_FILE), 'next'])
        elif key_event.matches('enter'):
            self.quit(0)
        elif key_event.matches('esc'):
            self.quit(1)

    def on_interrupt(self):
        self.quit(1)

    def on_eot(self):
        self.quit(1)

    def on_resize(self, new_size):
        self.refresh()

    def match_args(self):
        return [f'--match=id:{window_id}' for window_id in self.window_ids]

    def mark(self):
        if not self.window_ids:
            return
        text = self.line_edit.current_input
        if text:
            match_case = 'i' if text.islower() else ''
            match_type = match_case + self.mode
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'create-marker', match_arg, match_type, '1', text])
        else:
            self.remove_mark()

    def remove_mark(self):
        for match_arg in self.match_args():
            remote_control.main(['', 'remove-marker', match_arg])

    def quit(self, return_code):
        self.cached_values['last_search'] = self.line_edit.current_input
        self.remove_mark()
        if return_code:
            for match_arg in self.match_args():
                remote_control.main(['', 'scroll-window', match_arg, 'end'])
        self.quit_loop(return_code)
예제 #4
0
 def __init__(self, cli_opts: AskCLIOptions, prompt: str) -> None:
     self.cli_opts = cli_opts
     self.prompt = prompt
     from kittens.tui.line_edit import LineEdit
     self.line_edit = LineEdit(is_password=True)
예제 #5
0
파일: tui.py 프로젝트: zkzaza/kitty
 def test_line_edit(self):
     from kittens.tui.line_edit import LineEdit
     le = LineEdit()
     le.on_text('abcd', False)
     self.ae(le.cursor_pos, 4)
     for i in range(5):
         self.assertTrue(le.left()) if i < 4 else self.assertFalse(le.left())
         self.ae(le.cursor_pos, max(0, 3 - i))
     self.ae(le.pending_bell, True)
     le.clear()
     le.on_text('abcd', False), le.home()
     self.ae(le.cursor_pos, 0)
     for i in range(5):
         self.assertTrue(le.right()) if i < 4 else self.assertFalse(le.right())
         self.ae(le.cursor_pos, min(4, i + 1))
     self.ae(le.pending_bell, True)
     le.clear()
     le.on_text('abcd', False)
     self.ae(le.current_input, 'abcd')
     self.ae(le.cursor_pos, 4)
     self.ae(le.split_at_cursor(), ('abcd', ''))
     le.backspace()
     self.ae(le.current_input, 'abc')
     self.ae(le.cursor_pos, 3)
     self.assertFalse(le.pending_bell)
     le.backspace(num=2)
     self.ae(le.current_input, 'a')
     self.ae(le.cursor_pos, 1)
     self.assertFalse(le.pending_bell)
     le.backspace(num=2)
     self.ae(le.current_input, '')
     self.ae(le.cursor_pos, 0)
     le.backspace()
     self.assertTrue(le.pending_bell)
예제 #6
0
class Search(Handler):
    def __init__(self, cached_values, window_ids, error=''):
        self.cached_values = cached_values
        self.window_ids = window_ids
        self.error = error
        self.line_edit = LineEdit()
        last_search = cached_values.get('last_search', '')
        self.line_edit.add_text(last_search)
        self.text_marked = bool(last_search)
        self.mode = cached_values.get('mode', 'text')
        self.update_prompt()
        self.mark()

    def update_prompt(self):
        self.prompt = '~> ' if self.mode == 'regex' else '=> '

    def init_terminal_state(self):
        self.write(set_line_wrapping(False))
        self.write(set_window_title(_('Search')))

    def initialize(self):
        self.init_terminal_state()
        self.draw_screen()

    def draw_screen(self):
        self.write(clear_screen())
        if self.window_ids:
            input_text = self.line_edit.current_input
            if self.text_marked:
                self.line_edit.current_input = styled(input_text, reverse=True)
            self.line_edit.write(self.write, self.prompt)
            self.line_edit.current_input = input_text
        if self.error:
            with cursor(self.write):
                self.print('')
                for l in self.error.split('\n'):
                    self.print(l)

    def refresh(self):
        self.draw_screen()
        self.mark()

    def switch_mode(self):
        if self.mode == 'regex':
            self.mode = 'text'
        else:
            self.mode = 'regex'
        self.cached_values['mode'] = self.mode
        self.update_prompt()

    def on_text(self, text, in_bracketed_paste):
        if self.text_marked:
            self.text_marked = False
            self.line_edit.clear()
        self.line_edit.on_text(text, in_bracketed_paste)
        self.refresh()

    def on_key(self, key_event):
        if self.text_marked and key_event.key not in [
                'TAB', 'LEFT_CONTROL', 'RIGHT_CONTROL', 'LEFT_ALT',
                'RIGHT_ALT', 'LEFT_SHIFT', 'RIGHT_SHIFT', 'LEFT_SUPER',
                'RIGHT_SUPER'
        ]:
            self.text_marked = False
            self.refresh()

        if self.line_edit.on_key(key_event):
            self.refresh()
            return

        if key_event.matches('ctrl+u'):
            self.line_edit.clear()
            self.refresh()
        elif key_event.matches('ctrl+a'):
            self.line_edit.home()
            self.refresh()
        elif key_event.matches('ctrl+e'):
            self.line_edit.end()
            self.refresh()
        elif key_event.matches('tab'):
            self.switch_mode()
            self.refresh()
        elif key_event.matches('up'):
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'kitten', match_arg,
                     str(SCROLLMARK_FILE)])
        elif key_event.matches('down'):
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'kitten', match_arg,
                     str(SCROLLMARK_FILE), 'next'])
        elif key_event.matches('enter'):
            self.quit(0)
        elif key_event.matches('esc'):
            self.quit(1)

    def on_interrupt(self):
        self.quit(1)

    def on_eot(self):
        self.quit(1)

    def on_resize(self, new_size):
        self.refresh()

    def match_args(self):
        return [f'--match=id:{window_id}' for window_id in self.window_ids]

    def mark(self):
        if not self.window_ids:
            return
        text = self.line_edit.current_input
        if text:
            match_case = 'i' if text.islower() else ''
            match_type = match_case + self.mode
            for match_arg in self.match_args():
                remote_control.main(
                    ['', 'create-marker', match_arg, match_type, '1', text])
        else:
            self.remove_mark()

    def remove_mark(self):
        for match_arg in self.match_args():
            remote_control.main(['', 'remove-marker', match_arg])

    def quit(self, return_code):
        self.cached_values['last_search'] = self.line_edit.current_input
        self.remove_mark()
        if return_code:
            for match_arg in self.match_args():
                remote_control.main(['', 'scroll-window', match_arg, 'end'])
        self.quit_loop(return_code)