Exemple #1
0
    def __enter__(self):
        # init curses and it'screen wrapper
        self.screen = curses.initscr()
        self.display = Display(self.screen, self.encoding)

        # keyhandler
        self.keyhandler = KeyHandler(self.screen)

        # create view
        self.view = SelectorView(percol=self)
        self.command_candidate = SelectorCommand(self.model_candidate,
                                                 self.view)

        signal.signal(signal.SIGINT, lambda signum, frame: None)
        # handle special keys like <f1>, <down>, ...
        self.screen.keypad(True)

        curses.raw()
        curses.noecho()
        curses.cbreak()
        # Leave newline mode. Make percol distinguish between "C-m" and "C-j".
        curses.nonl()
        return self
Exemple #2
0
    def __enter__(self):
        # init curses and it'screen wrapper
        self.screen = curses.initscr()
        self.display = Display(self.screen, self.encoding)

        # keyhandler
        self.keyhandler = KeyHandler(self.screen)

        # create view
        self.view = SelectorView(percol=self)
        self.command_candidate = SelectorCommand(self.model_candidate, self.view)

        signal.signal(signal.SIGINT, lambda signum, frame: None)
        # handle special keys like <f1>, <down>, ...
        self.screen.keypad(True)

        curses.raw()
        curses.noecho()
        curses.cbreak()
        # Leave newline mode. Make percol distinguish between "C-m" and "C-j".
        curses.nonl()
        return self
Exemple #3
0
class Controller(object):

    # caret is '插入符号'
    def __init__(self, descriptors=None, encoding="utf-8", actions=None, query=None, caret=None, index=None):

        self.global_lock = threading.Lock()
        self.encoding = encoding
        self.actions = actions
        self.stdin = sys.stdin
        self.stdout = sys.stdout
        self.stderr = sys.stderr

        searcher = SearcherMulitQuery

        self.model_candidate = SelectorModel(percol=self, searcher=searcher, caret=caret, index=index)
        self.model = self.model_candidate

    def __enter__(self):
        # init curses and it'screen wrapper
        self.screen = curses.initscr()
        self.display = Display(self.screen, self.encoding)

        # keyhandler
        self.keyhandler = KeyHandler(self.screen)

        # create view
        self.view = SelectorView(percol=self)
        self.command_candidate = SelectorCommand(self.model_candidate, self.view)

        signal.signal(signal.SIGINT, lambda signum, frame: None)
        # handle special keys like <f1>, <down>, ...
        self.screen.keypad(True)

        curses.raw()
        curses.noecho()
        curses.cbreak()
        # Leave newline mode. Make percol distinguish between "C-m" and "C-j".
        curses.nonl()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        curses.nl()
        curses.endwin()
        self.execute_action()

    args_for_action = None

    def execute_action(self):
        selected_actions = self.model.get_selected_results_with_index()
        try:
            action = self.actions
            if action:
                action.act(selected_actions, self)
        except Exception as e:
            debug.log("execute_action", e)

    # ============================================================ #
    # Statuses
    # ============================================================ #
    @property
    def command(self):
        return self.command_candidate

    SEARCH_DELAY = 0.5

    def loop(self):
        self.view.refresh_display()
        self.result_updating_timer = None

        def search_and_refresh_display():
            self.model.do_search(self.model.query)
            self.view.refresh_display()

        while True:
            try:
                self.handle_key(self.screen.getch())
                if self.model.should_search_again():
                    # search again
                    with self.global_lock:
                        # critical section
                        if not self.result_updating_timer is None:
                            # clear timer
                            self.result_updating_timer.cancel()
                            self.result_updating_timer = None

                        # with bounce
                        t = threading.Timer(self.SEARCH_DELAY, search_and_refresh_display)
                        self.result_updating_timer = t
                        t.start()

                self.view.refresh_display()
            except TerminateLoop as e:
                return e.value

    # ============================================================ #
    # Key Handling
    # ============================================================ #

    keymap = {
        "C-i": lambda percol: percol.switch_model(),
        # text
        "C-h": lambda percol: percol.command.delete_backward_char(),
        "<backspace>": lambda percol: percol.command.delete_backward_char(),
        "C-w": lambda percol: percol.command.delete_backward_word(),
        "C-u": lambda percol: percol.command.clear_query(),
        "<dc>": lambda percol: percol.command.delete_forward_char(),
        # caret
        "<left>": lambda percol: percol.command.backward_char(),
        "<right>": lambda percol: percol.command.forward_char(),
        # line
        "<down>": lambda percol: percol.command.select_next(),
        "<up>": lambda percol: percol.command.select_previous(),
        # page
        "<npage>": lambda percol: percol.command.select_next_page(),
        "<ppage>": lambda percol: percol.command.select_previous_page(),
        # top / bottom
        "<home>": lambda percol: percol.command.select_top(),
        "<end>": lambda percol: percol.command.select_bottom(),
        # mark
        "C-SPC": lambda percol: percol.command.toggle_mark_and_next(),
        # finish
        "RET": lambda percol: percol.finish(),  # Is RET never sent?
        "C-m": lambda percol: percol.finish(),
        "C-j": lambda percol: percol.finish(),
        "C-c": lambda percol: percol.cancel(),
    }

    def import_keymap(self, keymap, reset=False):
        if reset:
            self.keymap = {}
        else:
            self.keymap = dict(self.keymap)
        for key, cmd in six.iteritems(keymap):
            self.keymap[key] = cmd

    # default
    last_key = None

    def handle_key(self, ch):
        if ch == curses.KEY_RESIZE:
            self.last_key = self.handle_resize(ch)
        elif ch != -1 and self.keyhandler.is_utf8_multibyte_key(ch):
            self.last_key = self.handle_utf8(ch)
        else:
            self.last_key = self.handle_normal_key(ch)

    def handle_resize(self, ch):
        self.display.update_screen_size()
        # XXX: trash -1 (it seems that resize key sends -1)
        self.keyhandler.get_key_for(self.screen.getch())
        return key.SPECIAL_KEYS[ch]

    def handle_utf8(self, ch):
        ukey = self.keyhandler.get_utf8_key_for(ch)
        self.model.insert_string(ukey)
        return ukey.encode(self.encoding)

    def handle_normal_key(self, ch):
        k = self.keyhandler.get_key_for(ch)
        if k in self.keymap:
            self.keymap[k](self)
        elif self.keyhandler.is_displayable_key(ch):
            self.model.insert_char(ch)
        return k

    # ------------------------------------------------------------ #
    # Finish / Cancel
    # ------------------------------------------------------------ #

    def finish(self):
        # save selected candidates and use them later (in execute_action)
        raise TerminateLoop(self.finish_with_exit_code())  # success

    def cancel(self):
        raise TerminateLoop(self.cancel_with_exit_code())  # failure

    def finish_with_exit_code(self):
        self.args_for_action = self.model_candidate.get_selected_results_with_index()
        return 0

    def cancel_with_exit_code(self):
        return 1
Exemple #4
0
class Controller(object):

    # caret is '插入符号'
    def __init__(self,
                 descriptors=None,
                 encoding="utf-8",
                 actions=None,
                 query=None,
                 caret=None,
                 index=None):

        self.global_lock = threading.Lock()
        self.encoding = encoding
        self.actions = actions
        self.stdin = sys.stdin
        self.stdout = sys.stdout
        self.stderr = sys.stderr

        searcher = SearcherMulitQuery

        self.model_candidate = SelectorModel(percol=self,
                                             searcher=searcher,
                                             caret=caret,
                                             index=index)
        self.model = self.model_candidate

    def __enter__(self):
        # init curses and it'screen wrapper
        self.screen = curses.initscr()
        self.display = Display(self.screen, self.encoding)

        # keyhandler
        self.keyhandler = KeyHandler(self.screen)

        # create view
        self.view = SelectorView(percol=self)
        self.command_candidate = SelectorCommand(self.model_candidate,
                                                 self.view)

        signal.signal(signal.SIGINT, lambda signum, frame: None)
        # handle special keys like <f1>, <down>, ...
        self.screen.keypad(True)

        curses.raw()
        curses.noecho()
        curses.cbreak()
        # Leave newline mode. Make percol distinguish between "C-m" and "C-j".
        curses.nonl()
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        curses.nl()
        curses.endwin()
        self.execute_action()

    args_for_action = None

    def execute_action(self):
        selected_actions = self.model.get_selected_results_with_index()
        try:
            action = self.actions
            if action:
                action.act(selected_actions, self)
        except Exception as e:
            debug.log("execute_action", e)

    # ============================================================ #
    # Statuses
    # ============================================================ #
    @property
    def command(self):
        return self.command_candidate

    SEARCH_DELAY = 0.5

    def loop(self):
        self.view.refresh_display()
        self.result_updating_timer = None

        def search_and_refresh_display():
            self.model.do_search(self.model.query)
            self.view.refresh_display()

        while True:
            try:
                self.handle_key(self.screen.getch())
                if self.model.should_search_again():
                    # search again
                    with self.global_lock:
                        # critical section
                        if not self.result_updating_timer is None:
                            # clear timer
                            self.result_updating_timer.cancel()
                            self.result_updating_timer = None

                        # with bounce
                        t = threading.Timer(self.SEARCH_DELAY,
                                            search_and_refresh_display)
                        self.result_updating_timer = t
                        t.start()

                self.view.refresh_display()
            except TerminateLoop as e:
                return e.value

    # ============================================================ #
    # Key Handling
    # ============================================================ #

    keymap = {
        "C-i": lambda percol: percol.switch_model(),
        # text
        "C-h": lambda percol: percol.command.delete_backward_char(),
        "<backspace>": lambda percol: percol.command.delete_backward_char(),
        "C-w": lambda percol: percol.command.delete_backward_word(),
        "C-u": lambda percol: percol.command.clear_query(),
        "<dc>": lambda percol: percol.command.delete_forward_char(),
        # caret
        "<left>": lambda percol: percol.command.backward_char(),
        "<right>": lambda percol: percol.command.forward_char(),
        # line
        "<down>": lambda percol: percol.command.select_next(),
        "<up>": lambda percol: percol.command.select_previous(),
        # page
        "<npage>": lambda percol: percol.command.select_next_page(),
        "<ppage>": lambda percol: percol.command.select_previous_page(),
        # top / bottom
        "<home>": lambda percol: percol.command.select_top(),
        "<end>": lambda percol: percol.command.select_bottom(),
        # mark
        "C-SPC": lambda percol: percol.command.toggle_mark_and_next(),
        # finish
        "RET": lambda percol: percol.finish(),  # Is RET never sent?
        "C-m": lambda percol: percol.finish(),
        "C-j": lambda percol: percol.finish(),
        "C-c": lambda percol: percol.cancel()
    }

    def import_keymap(self, keymap, reset=False):
        if reset:
            self.keymap = {}
        else:
            self.keymap = dict(self.keymap)
        for key, cmd in six.iteritems(keymap):
            self.keymap[key] = cmd

    # default
    last_key = None

    def handle_key(self, ch):
        if ch == curses.KEY_RESIZE:
            self.last_key = self.handle_resize(ch)
        elif ch != -1 and self.keyhandler.is_utf8_multibyte_key(ch):
            self.last_key = self.handle_utf8(ch)
        else:
            self.last_key = self.handle_normal_key(ch)

    def handle_resize(self, ch):
        self.display.update_screen_size()
        # XXX: trash -1 (it seems that resize key sends -1)
        self.keyhandler.get_key_for(self.screen.getch())
        return key.SPECIAL_KEYS[ch]

    def handle_utf8(self, ch):
        ukey = self.keyhandler.get_utf8_key_for(ch)
        self.model.insert_string(ukey)
        return ukey.encode(self.encoding)

    def handle_normal_key(self, ch):
        k = self.keyhandler.get_key_for(ch)
        if k in self.keymap:
            self.keymap[k](self)
        elif self.keyhandler.is_displayable_key(ch):
            self.model.insert_char(ch)
        return k

    # ------------------------------------------------------------ #
    # Finish / Cancel
    # ------------------------------------------------------------ #

    def finish(self):
        # save selected candidates and use them later (in execute_action)
        raise TerminateLoop(self.finish_with_exit_code())  # success

    def cancel(self):
        raise TerminateLoop(self.cancel_with_exit_code())  # failure

    def finish_with_exit_code(self):
        self.args_for_action = self.model_candidate.\
            get_selected_results_with_index()
        return 0

    def cancel_with_exit_code(self):
        return 1