示例#1
0
def launch_isearch(cfstore, rcfile=None, input_encoding=None,
                   base_query=None, query=None, query_template=None, **kwds):
    from percol import Percol
    from percol import tty
    import percol.actions as actions

    from .database import DataBase

    config = cfstore.get_config()
    default = lambda val, defv: defv if val is None else val

    # Pass db instance to finder.  Not clean but works and no harm.
    RashFinder.db = DataBase(cfstore.db_path)
    RashFinder.base_query = default(base_query, config.isearch.base_query)
    RashFinder.rashconfig = config

    template = default(query_template, config.isearch.query_template)
    default_query = default(query, config.isearch.query)

    ttyname = tty.get_ttyname()
    with open(ttyname, "r+w") as tty_f:
        with Percol(descriptors=tty.reconnect_descriptors(tty_f),
                    finder=RashFinder,
                    actions=(actions.output_to_stdout,),
                    # This will be used if the first call for RashFinder.find
                    # fails to fetch collections from DB.
                    candidates=[],
                    query=template.format(default_query),
                    **kwds) as percol:
            load_rc(percol, rcfile, input_encoding)
            exit_code = percol.loop()

    exit(exit_code)
示例#2
0
def select_from_list(list):
    """Select an option from an interactive list made with Percol"""
    candidates = [element[0] for element in list]
    with Percol(actions=[],
                descriptors={
                    'stdin': "",
                    'stdout': "",
                    'stderr': ""
                },
                candidates=iter(candidates)) as p:
        p.loop()
    selected_element = p.model_candidate.get_selected_result()
    result = [element for element in list if element[0] == selected_element]
    return result[0]
示例#3
0
def cli_query(query, candidates):
    # get ttyname
    ttyname = tty.get_ttyname()
    if not ttyname:
        logger.critical(
            """No tty name is given and failed to guess it from descriptors.  Maybe all descriptors are redirected."""
        )
        sys.exit(1)

    # decide which encoding to use
    locale.setlocale(locale.LC_ALL, '')
    output_encoding = locale.getpreferredencoding()

    with open(ttyname, "wb+", buffering=0) as tty_f:
        if not tty_f.isatty():
            logger.critical("{0} is not a tty file".format(ttyname))
            sys.exit(2)

        # setup actions
        acts = (get_selected_string, get_selected_string)

        # arrange finder class
        from percol.finder import FinderMultiQueryString
        candidate_finder_class = action_finder_class = FinderMultiQueryString

        with Percol(descriptors=tty.reconnect_descriptors(tty_f),
                    candidates=candidates,
                    actions=acts,
                    finder=candidate_finder_class,
                    action_finder=action_finder_class,
                    query=query,
                    encoding=output_encoding) as percol:
            # finder settings from option values
            percol.model_candidate.finder.lazy_finding = True
            percol.model_candidate.finder.case_insensitive = True
            percol.model_candidate.finder.invert_match = False
            # enter main loop
            exit_code = percol.loop()
    if exit_code:
        logger.error('Query Canceled!')
        sys.exit(exit_code)

    if selected_str:
        return selected_str
    else:
        return ['']
示例#4
0
def main():
    from percol import __version__
    parser = OptionParser(usage="Usage: %prog [options] [FILE]",
                          version="%prog {0}".format(__version__))
    setup_options(parser)
    options, args = parser.parse_args()

    if options.peep:
        exit(1)

    def exit_program(msg=None, show_help=True):
        if not msg is None:
            print(msg)
        if show_help:
            parser.print_help()
        exit(1)

    # get ttyname
    ttyname = options.tty or tty.get_ttyname()
    if not ttyname:
        exit_program(
            error_message(
                """No tty name is given and failed to guess it from descriptors.
Maybe all descriptors are redirecred."""))

    # decide which encoding to use
    output_encoding = set_proper_locale(options)
    input_encoding = options.input_encoding

    def open_tty(ttyname):
        if six.PY2:
            return open(ttyname, "r+w")
        else:
            # See https://github.com/stefanholek/term/issues/1
            return open(ttyname, "wb+", buffering=0)

    with open_tty(ttyname) as tty_f:
        if not tty_f.isatty():
            exit_program(error_message(
                "{0} is not a tty file".format(ttyname)),
                         show_help=False)

        filename = args[0] if len(args) > 0 else None

        if filename and not os.access(filename, os.R_OK):
            exit_program(error_message("Cannot read a file '" + filename +
                                       "'"),
                         show_help=False)

        if filename is None and sys.stdin.isatty():
            tty_f.write(INSTRUCTION_TEXT.encode(output_encoding))
            exit_program(show_help=False)

        # read input
        try:
            candidates = read_input(filename,
                                    input_encoding,
                                    reverse=options.reverse)
        except KeyboardInterrupt:
            exit_program("Canceled", show_help=False)

        # setup actions
        import percol.actions as actions
        if (options.quote):
            acts = (actions.output_to_stdout_double_quote, )
        else:
            acts = (actions.output_to_stdout,
                    actions.output_to_stdout_double_quote)

        # arrange finder class
        candidate_finder_class = action_finder_class = decide_match_method(
            options)

        def set_finder_attribute_from_option(finder_instance):
            finder_instance.lazy_finding = not options.eager
            finder_instance.case_insensitive = not options.case_sensitive
            finder_instance.invert_match = options.invert_match

        def set_if_not_none(src, dest, name):
            value = getattr(src, name)
            if value is not None:
                setattr(dest, name, value)

        with Percol(descriptors=tty.reconnect_descriptors(tty_f),
                    candidates=candidates,
                    actions=acts,
                    finder=candidate_finder_class,
                    action_finder=action_finder_class,
                    query=options.query,
                    caret=options.caret,
                    index=options.index,
                    encoding=output_encoding) as percol:
            # load run-command file
            load_rc(percol, options.rcfile)
            # override prompts
            if options.prompt is not None:
                percol.view.__class__.PROMPT = property(
                    lambda self: options.prompt)
            if options.right_prompt is not None:
                percol.view.__class__.RPROMPT = property(
                    lambda self: options.right_prompt)
            # evalutate strings specified by the option argument
            if options.string_to_eval is not None:
                eval_string(percol, options.string_to_eval,
                            locale.getpreferredencoding())
            # finder settings from option values
            set_finder_attribute_from_option(percol.model_candidate.finder)
            # view settings from option values
            set_if_not_none(options, percol.view, 'prompt_on_top')
            set_if_not_none(options, percol.view, 'results_top_down')
            # enter main loop
            if options.auto_fail and percol.has_no_candidate():
                exit_code = percol.cancel_with_exit_code()
            elif options.auto_match and percol.has_only_one_candidate():
                exit_code = percol.finish_with_exit_code()
            else:
                exit_code = percol.loop()

        exit(exit_code)