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)
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]
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 ['']
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)